@deeeed/metamask-harness 0.79.0 → 0.81.0
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/CHANGELOG.md +73 -0
- package/README.md +1 -1
- package/adapters/extension/ensure-browser.sh +2 -2
- package/adapters/extension/inject.mjs +0 -1
- package/adapters/extension/launch-browser.cjs +39 -613
- package/adapters/extension/readiness.mjs +2 -5
- package/adapters/extension/reattach.sh +2 -2
- package/adapters/extension/stamp-runtime-title.cjs +1 -1
- package/adapters/manifest.json +16 -64
- package/adapters/mobile/bridge-runtime/cdp-bridge.cjs +57 -1358
- package/adapters/mobile/bridge-runtime/teaching.cjs +20 -0
- package/adapters/mobile/inject.sh +16 -0
- package/adapters/mobile/launch-console-forwarder.cjs +1 -2
- package/adapters/mobile/open-device.sh +2 -2
- package/adapters/mobile/reload-app.mjs +4 -4
- package/adapters/mobile/reset-app-data.sh +1 -1
- package/adapters/mobile/start-console-forwarder.sh +3 -2
- package/adapters/mobile/start-metro.sh +17 -12
- package/adapters/mobile/wait-for-bridge.cjs +2 -2
- package/adapters/shared/harness-source-fingerprint.mjs +13 -8
- package/adapters/shared/open-debug.mjs +2 -2
- package/adapters/shared/sync-wallet-fixture.sh +8 -5
- package/adapters/terminal/cleanup.mjs +2 -1
- package/adapters/terminal/inject.mjs +2 -1
- package/adapters/terminal/launch.mjs +17 -13
- package/adapters/terminal/lib/mainnet-guard.mjs +9 -0
- package/adapters/terminal/lib/readiness.mjs +20 -12
- package/adapters/terminal/policy.mjs +35 -0
- package/adapters/terminal/verify.mjs +10 -3
- package/adapters/terminal/wallet-host.mjs +43 -225
- package/bin/mm-harness +9 -28
- package/dist/adapters/checkout-files.js +16 -0
- package/dist/adapters/console-capture.js +14 -1
- package/dist/adapters/core/actions.js +8 -4
- package/dist/adapters/core/overlay.js +1 -1
- package/dist/adapters/core/readiness.js +28 -1
- package/dist/adapters/core/run.js +2 -2
- package/dist/adapters/core/surface.js +16 -1
- package/dist/adapters/extension/actions.js +6 -2
- package/dist/adapters/extension/browser-pid.js +56 -0
- package/dist/adapters/extension/console-capture.js +1 -1
- package/dist/adapters/extension/doctor-checks.js +1 -1
- package/dist/adapters/extension/ensure-ready.js +5 -4
- package/dist/adapters/extension/extension-id.js +1 -1
- package/dist/adapters/extension/feature-flags.js +1 -1
- package/dist/adapters/extension/fixtures.js +1 -2
- package/dist/adapters/extension/launch.js +4 -5
- package/dist/adapters/extension/launched-browser.js +1 -2
- package/dist/adapters/extension/network-observer.js +14 -1
- package/dist/adapters/extension/overlay.js +1 -1
- package/dist/adapters/extension/product-config.js +1 -1
- package/dist/adapters/extension/readiness.js +1 -1
- package/dist/adapters/extension/reload.js +1 -1
- package/dist/adapters/extension/run.js +135 -14
- package/dist/adapters/extension/runtime-decision.js +2 -1
- package/dist/adapters/extension/runtime.js +9 -5
- package/dist/adapters/extension/surface.js +15 -2
- package/dist/adapters/extension/verify.js +2 -2
- package/dist/adapters/harness-freshness.js +2 -1
- package/dist/adapters/mobile/actions.js +4 -1
- package/dist/adapters/mobile/android-gfxinfo-performance.js +1 -3
- package/dist/adapters/mobile/app-identity.js +10 -0
- package/dist/adapters/mobile/doctor-checks.js +1 -1
- package/dist/adapters/mobile/fixtures.js +1 -1
- package/dist/adapters/mobile/launch.js +27 -28
- package/dist/adapters/mobile/lifecycle.js +1 -1
- package/dist/adapters/mobile/metro-env.js +9 -59
- package/dist/adapters/mobile/network-observer.js +68 -0
- package/dist/adapters/mobile/performance-observer.js +2 -4
- package/dist/adapters/mobile/prepare-target.js +1 -1
- package/dist/adapters/mobile/prepare.js +3 -4
- package/dist/adapters/mobile/provision.js +1 -1
- package/dist/adapters/mobile/readiness.js +1 -1
- package/dist/adapters/mobile/recording-target.js +15 -0
- package/dist/adapters/mobile/release-artifact-state.js +1 -1
- package/dist/adapters/mobile/reload.js +1 -1
- package/dist/adapters/mobile/run.js +39 -15
- package/dist/adapters/mobile/runtime-decision.js +2 -4
- package/dist/adapters/mobile/source-freshness.js +22 -126
- package/dist/adapters/mobile/surface.js +26 -3
- package/dist/adapters/mobile/ui.js +16 -5
- package/dist/adapters/mobile/verify.js +2 -3
- package/dist/adapters/performance/cdp-trace.js +1 -1
- package/dist/adapters/performance/device-platform.js +1 -1
- package/dist/adapters/perps-order-inputs.js +36 -0
- package/dist/adapters/proof-failure.js +11 -0
- package/dist/adapters/slot-ports.js +1 -1
- package/dist/adapters/surface.js +1 -0
- package/dist/adapters/terminal/actions.js +4 -1
- package/dist/adapters/terminal/console-capture.js +1 -1
- package/dist/adapters/terminal/doctor-checks.js +2 -0
- package/dist/adapters/terminal/launch.js +4 -1
- package/dist/adapters/terminal/overlay.js +8 -1
- package/dist/adapters/terminal/run.js +33 -5
- package/dist/adapters/terminal/surface.js +9 -1
- package/dist/adapters.js +27 -7
- package/dist/advisor-policy.js +1 -1
- package/dist/checkout-view.js +1 -2
- package/dist/cli.js +59 -21
- package/dist/command-contract.js +1 -26
- package/dist/commands/check.js +33 -10
- package/dist/commands/checklist.js +1 -1
- package/dist/commands/completion-candidates.js +6 -14
- package/dist/commands/config.js +2 -2
- package/dist/commands/core-readiness.js +12 -7
- package/dist/commands/debug.js +3 -3
- package/dist/commands/device-target.js +5 -5
- package/dist/commands/doctor.js +2 -14
- package/dist/commands/domain.js +2 -2
- package/dist/commands/ensure-ready.js +1 -7
- package/dist/commands/fixtures.js +5 -6
- package/dist/commands/help.js +3 -4
- package/dist/commands/launch/device.js +10 -17
- package/dist/commands/launch/extension.js +2 -8
- package/dist/commands/launch/mobile.js +1 -1
- package/dist/commands/logs.js +3 -3
- package/dist/commands/mobile-device-view.js +4 -2
- package/dist/commands/overlay.js +110 -0
- package/dist/commands/pin.js +1 -1
- package/dist/commands/pr-body.js +2 -2
- package/dist/commands/prepare.js +4 -9
- package/dist/commands/provision.js +3 -12
- package/dist/commands/recipe-advice.js +1 -2
- package/dist/commands/recipe-quality.js +2 -3
- package/dist/commands/resolve-extension.js +1 -7
- package/dist/commands/review.js +4 -4
- package/dist/commands/runtime-decision.js +1 -6
- package/dist/commands/runtime-health.js +1 -7
- package/dist/commands/runtime-launch.js +1 -13
- package/dist/commands/self-test.js +5 -8
- package/dist/commands/status-watch.js +1 -2
- package/dist/commands/status.js +2 -5
- package/dist/commands/task-init.js +2 -3
- package/dist/commands/tutorial.js +2 -2
- package/dist/commands/update.js +1 -1
- package/dist/completions-cache.js +1 -1
- package/dist/console-classifier.js +19 -0
- package/dist/doctor.js +2 -3
- package/dist/engine.js +57 -0
- package/dist/funding-execution-context.js +96 -1
- package/dist/host.js +32 -0
- package/dist/index.js +1 -6
- package/dist/live-tsx.js +49 -0
- package/dist/mm-harness-cli.js +4 -6
- package/dist/paths.js +34 -64
- package/dist/performance-observation.js +3 -5
- package/dist/progress.js +1 -1
- package/dist/recipe-assistance-context.js +6 -9
- package/dist/recipe-security.js +2 -59
- package/dist/review/knowledge.js +2 -2
- package/dist/runner.js +7 -4
- package/dist/runtime-context.js +1 -1
- package/dist/task-view.js +2 -3
- package/docs/CONTRIBUTING.md +5 -3
- package/docs/RECIPES.md +31 -3
- package/docs/cli-contract.md +2 -2
- package/docs/feature-guard.md +90 -0
- package/library/README.md +3 -1
- package/library/actions/core/perps/_controller.mjs +153 -134
- package/library/actions/core/perps/_rewards.mjs +186 -0
- package/library/actions/core/perps/close_positions.mjs +1 -1
- package/library/actions/core/perps/place_order.mjs +167 -45
- package/library/actions/core/perps/quote_fees.mjs +61 -0
- package/library/actions/core/wallet/list_accounts.mjs +14 -57
- package/library/actions/extension/feature_flags/state.mjs +1 -1
- package/library/actions/extension/perps/close_visible_position.mjs +5 -0
- package/library/actions/extension/perps/edit_margin.mjs +4 -0
- package/library/actions/extension/perps/mutation-receipt.mjs +95 -3
- package/library/actions/extension/perps/perps.mjs +320 -3
- package/library/actions/extension/perps/place_order.mjs +3 -1
- package/library/actions/extension/perps/update_position_tpsl.mjs +4 -0
- package/library/actions/extension/platform/cdp.mjs +73 -11
- package/library/actions/harness-exports.mjs +1 -6
- package/library/actions/mobile/app/network-control.mjs +6 -8
- package/library/actions/mobile/perps/perps.mjs +216 -11
- package/library/actions/mobile/perps/place_order.mjs +3 -1
- package/library/actions/mobile/perps/prepare_local_snapshot_endpoint.mjs +1 -1
- package/library/actions/mobile/platform/bridge.mjs +8 -8
- package/library/actions/mobile/platform/native-session-name.mjs +21 -1
- package/library/actions/mobile/platform/native-session.mjs +3 -4
- package/library/actions/mobile/platform/observe-ui.mjs +12 -6
- package/library/actions/mobile/ui/native-navigation.mjs +4 -3
- package/library/actions/mobile/wallet/native-ui.mjs +3 -2
- package/library/actions/shared/analytics/_adapter.mjs +1 -1
- package/library/actions/shared/console-findings.mjs +1 -1
- package/library/actions/shared/perps/order-policy.mjs +177 -0
- package/library/actions/shared/wallet/fixture-accounts.mjs +84 -0
- package/library/actions/terminal/app/launch.mjs +3 -2
- package/library/actions/terminal/platform/hud.mjs +2 -1
- package/library/actions/terminal/platform/page.mjs +2 -1
- package/library/actions/terminal/platform/runtime.mjs +2 -1
- package/library/actions/terminal/wallet/_signature-log.mjs +40 -161
- package/library/actions/terminal/wallet/assert_signatures.mjs +6 -12
- package/library/actions/terminal/wallet/read_signatures.mjs +10 -9
- package/library/manifests/core.action-manifest.json +87 -13
- package/library/manifests/extension.action-manifest.json +4 -0
- package/library/manifests/mobile.action-manifest.json +12 -0
- package/package.json +8 -9
- package/site/assets/help-recipes.json +1 -0
- package/adapters/extension/lib/slot-title.cjs +0 -292
- package/adapters/mobile/bridge-runtime/console-forwarder.cjs +0 -472
- package/adapters/mobile/bridge-runtime/lib/bridge-errors.cjs +0 -125
- package/adapters/mobile/bridge-runtime/lib/cdp-broker.cjs +0 -1055
- package/adapters/mobile/bridge-runtime/lib/cdp-eval.cjs +0 -110
- package/adapters/mobile/bridge-runtime/lib/config.cjs +0 -61
- package/adapters/mobile/bridge-runtime/lib/console-format.cjs +0 -53
- package/adapters/mobile/bridge-runtime/lib/devtools-proxy.cjs +0 -177
- package/adapters/mobile/bridge-runtime/lib/issue-capture.cjs +0 -446
- package/adapters/mobile/bridge-runtime/lib/match-bridge-target.cjs +0 -84
- package/adapters/mobile/bridge-runtime/lib/target-discovery.cjs +0 -403
- package/adapters/mobile/bridge-runtime/lib/ws-client.cjs +0 -116
- package/adapters/mobile/coalesce-metro-log.cjs +0 -24
- package/adapters/mobile/launch-metro.cjs +0 -77
- package/adapters/mobile/metro-config.cjs +0 -98
- package/adapters/mobile/metro-log-generation.cjs +0 -106
- package/adapters/terminal/lib/origin.mjs +0 -30
- package/adapters/terminal/lib/page-script.mjs +0 -246
- package/adapters/terminal/lib/strict-wallet.mjs +0 -138
- package/dist/adapters/mobile/frame-metrics.js +0 -118
- package/dist/adapters/mobile/video-recorder.js +0 -289
- package/dist/artifact-files.js +0 -92
- package/dist/checkout-lock.js +0 -149
- package/dist/cli-color.js +0 -98
- package/dist/command-journal.js +0 -308
- package/dist/commands/call.js +0 -685
- package/dist/commands/last.js +0 -60
- package/dist/commands/launch/index.js +0 -109
- package/dist/commands/list-executables.js +0 -247
- package/dist/commands/manifest.js +0 -488
- package/dist/commands/parse-args.js +0 -279
- package/dist/commands/reload.js +0 -41
- package/dist/commands/run-engine.js +0 -1340
- package/dist/commands/run-report.js +0 -241
- package/dist/commands/run.js +0 -751
- package/dist/commands/shared.js +0 -323
- package/dist/commands/stop.js +0 -60
- package/dist/devices.js +0 -100
- package/dist/discovery.js +0 -15
- package/dist/execution-provenance.js +0 -332
- package/dist/harness.js +0 -451
- package/dist/heal-bounds.js +0 -137
- package/dist/json-stream.js +0 -60
- package/dist/leaf-invoke.js +0 -19
- package/dist/library-provenance.js +0 -33
- package/dist/live-adapter-contract.js +0 -380
- package/dist/metamask-action-validation.js +0 -68
- package/dist/network-observation.js +0 -290
- package/dist/recording-target.js +0 -120
- package/dist/run-diagnostics.js +0 -364
- package/dist/run-recording.js +0 -481
- package/dist/runtime-proof.js +0 -90
- package/library/actions/mobile/platform/tool-paths.mjs +0 -123
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { EXIT, spawnScriptStreaming } from "@farmslot/recipe-cli/harness";
|
|
1
2
|
import path from "node:path";
|
|
2
|
-
import { EXIT, spawnScriptStreaming } from "../../commands/shared.js";
|
|
3
3
|
import { runnerDir } from "../../paths.js";
|
|
4
4
|
import { FIXTURE_STREAM_TIMEOUT_MS } from "../../commands/fixtures.js";
|
|
5
5
|
const FIXTURE_BRIDGE_READY_TIMEOUT_MS = 18e4;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
+
import { recipeRuntimePath, EXIT, str, writeInteractiveProgress } from "@farmslot/recipe-cli/harness";
|
|
2
3
|
import { applyDeviceTargeting } from "../../commands/device-target.js";
|
|
3
4
|
import { launchMobile } from "../../commands/launch/mobile.js";
|
|
4
5
|
import { shellQuote } from "../../commands/launch/quote.js";
|
|
5
|
-
|
|
6
|
-
import { RECOVERY_CODE } from "../../heal-bounds.js";
|
|
7
|
-
import { recipeRuntimePath } from "../../paths.js";
|
|
6
|
+
const METRO_RESTARTED = "metro.restarted";
|
|
8
7
|
function mobileProvisioningBlocked(output) {
|
|
9
8
|
return /open-device: configured iOS simulator '.+' does not exist|open-device: no MetaMask bundle found|fast mode requires an installed (?:iOS dev client|Android dev client)/u.test(output);
|
|
10
9
|
}
|
|
@@ -17,8 +16,8 @@ function ambiguousConfiguredIosSimulator(output) {
|
|
|
17
16
|
function mobileBridgeTargetMissing(output) {
|
|
18
17
|
return /no bridge target matched|wait-for-bridge: readiness deadline expired/iu.test(output);
|
|
19
18
|
}
|
|
20
|
-
function mobileProvisionCommand(target,
|
|
21
|
-
const platform =
|
|
19
|
+
function mobileProvisionCommand(target, platformTarget) {
|
|
20
|
+
const platform = platformTarget === "android" ? "android" : "ios";
|
|
22
21
|
const device = platform === "ios" ? process.env.SIM_UDID || process.env.IOS_SIMULATOR : process.env.ADB_SERIAL || process.env.ANDROID_SERIAL || process.env.ANDROID_DEVICE;
|
|
23
22
|
const parts = ["mm-harness", "provision", "runway", platform, "--adapter", "mobile", "--target", shellQuote(target)];
|
|
24
23
|
if (device) parts.push("--device", shellQuote(device));
|
|
@@ -27,11 +26,11 @@ function mobileProvisionCommand(target, mobileTarget) {
|
|
|
27
26
|
function isIosSimulatorUdid(value) {
|
|
28
27
|
return /^[0-9A-Fa-f-]{36}$/u.test(value);
|
|
29
28
|
}
|
|
30
|
-
function launchDeviceLabel(
|
|
31
|
-
if (
|
|
29
|
+
function launchDeviceLabel(platformTarget) {
|
|
30
|
+
if (platformTarget === "android") {
|
|
32
31
|
return process.env.ANDROID_TARGET_DEVICE_NAME || process.env.ADB_SERIAL || process.env.ANDROID_SERIAL || process.env.ANDROID_DEVICE || "android device";
|
|
33
32
|
}
|
|
34
|
-
if (
|
|
33
|
+
if (platformTarget === "ios") {
|
|
35
34
|
return process.env.IOS_SIMULATOR || process.env.SIM_UDID || "iOS simulator";
|
|
36
35
|
}
|
|
37
36
|
return process.env.IOS_SIMULATOR || process.env.ADB_SERIAL || "booted device";
|
|
@@ -51,22 +50,22 @@ function metroLaunchEvidence(target) {
|
|
|
51
50
|
}
|
|
52
51
|
}
|
|
53
52
|
const mobileLaunchProfile = {
|
|
54
|
-
refuseFlags({
|
|
55
|
-
if (!
|
|
53
|
+
refuseFlags({ platformTarget }) {
|
|
54
|
+
if (!platformTarget) {
|
|
56
55
|
return { message: "target is required for mobile.", userAction: "mm-harness launch ios or mm-harness launch android" };
|
|
57
56
|
}
|
|
58
57
|
return void 0;
|
|
59
58
|
},
|
|
60
|
-
applyEnv({ adapter, options,
|
|
59
|
+
applyEnv({ adapter, options, platformTarget, target }) {
|
|
61
60
|
const device = str(options, "device");
|
|
62
|
-
if (!device &&
|
|
61
|
+
if (!device && platformTarget !== "ios" && platformTarget !== "android") return void 0;
|
|
63
62
|
const targetingOptions = {
|
|
64
63
|
...options,
|
|
65
|
-
...
|
|
64
|
+
...platformTarget ? { platform: platformTarget } : {}
|
|
66
65
|
};
|
|
67
66
|
const result = applyDeviceTargeting("launch", adapter, targetingOptions, { gate: false, rerun: "" });
|
|
68
67
|
if ("code" in result) {
|
|
69
|
-
if (
|
|
68
|
+
if (platformTarget === "ios" && result.code === "DEVICE_NOT_FOUND") {
|
|
70
69
|
process.env.IOS_SIMULATOR = device;
|
|
71
70
|
process.env.SIM_UDID = isIosSimulatorUdid(device) ? device : "";
|
|
72
71
|
process.env.ADB_SERIAL = "";
|
|
@@ -77,7 +76,7 @@ const mobileLaunchProfile = {
|
|
|
77
76
|
return result;
|
|
78
77
|
}
|
|
79
78
|
}
|
|
80
|
-
if (
|
|
79
|
+
if (platformTarget === "android" && device && !process.env.ADB_SERIAL && !process.env.ANDROID_SERIAL) {
|
|
81
80
|
return {
|
|
82
81
|
ok: false,
|
|
83
82
|
code: "DEVICE_WRONG_PLATFORM",
|
|
@@ -85,7 +84,7 @@ const mobileLaunchProfile = {
|
|
|
85
84
|
userAction: `mm-harness status --target ${shellQuote(target)} --all-devices --json`
|
|
86
85
|
};
|
|
87
86
|
}
|
|
88
|
-
if (
|
|
87
|
+
if (platformTarget === "ios" && device && !process.env.IOS_SIMULATOR) {
|
|
89
88
|
return {
|
|
90
89
|
ok: false,
|
|
91
90
|
code: "DEVICE_WRONG_PLATFORM",
|
|
@@ -95,17 +94,17 @@ const mobileLaunchProfile = {
|
|
|
95
94
|
}
|
|
96
95
|
return void 0;
|
|
97
96
|
},
|
|
98
|
-
start({ options,
|
|
99
|
-
const device = str(options, "device") ?? (
|
|
97
|
+
start({ options, platformTarget, machine, tier, wantClearMetro }) {
|
|
98
|
+
const device = str(options, "device") ?? (platformTarget === "android" ? process.env.ADB_SERIAL ?? process.env.ANDROID_SERIAL : process.env.IOS_SIMULATOR ?? process.env.SIM_UDID) ?? "configured device";
|
|
100
99
|
const watcherPort = str(options, "watcherPort") ?? process.env.WATCHER_PORT ?? "auto";
|
|
101
100
|
writeInteractiveProgress(
|
|
102
101
|
machine,
|
|
103
|
-
`\u2192 mobile launch \u2014 ${
|
|
102
|
+
`\u2192 mobile launch \u2014 ${platformTarget} \xB7 ${tier === "build" ? "native build" : "quick readiness"} \xB7 ${device} \xB7 Metro ${watcherPort === "auto" ? "auto" : `:${watcherPort}`}${wantClearMetro ? " \xB7 clear cache" : ""}`
|
|
104
103
|
);
|
|
105
104
|
},
|
|
106
105
|
nativeInputs: ["ios", "android", "package.json", "yarn.lock"],
|
|
107
|
-
rebuildCommand: ({
|
|
108
|
-
compose: ({ target,
|
|
106
|
+
rebuildCommand: ({ platformTarget }) => `mm-harness launch ${platformTarget} --build`,
|
|
107
|
+
compose: ({ target, platformTarget, machine, remoteFlagRequest }, tier, restartApp, clearMetro) => launchMobile(target, platformTarget, tier, machine, restartApp, clearMetro, remoteFlagRequest?.flags),
|
|
109
108
|
classify(_launch, output) {
|
|
110
109
|
if (output.includes("open-device: Android device is locked.")) {
|
|
111
110
|
return {
|
|
@@ -130,7 +129,7 @@ const mobileLaunchProfile = {
|
|
|
130
129
|
return void 0;
|
|
131
130
|
},
|
|
132
131
|
async beforeHeal(launch, attempt, state) {
|
|
133
|
-
const { target,
|
|
132
|
+
const { target, platformTarget, tier } = launch;
|
|
134
133
|
const output = attempt.output;
|
|
135
134
|
const missingIosSimulator = missingConfiguredIosSimulator(output);
|
|
136
135
|
const ambiguousIosSimulator = ambiguousConfiguredIosSimulator(output);
|
|
@@ -157,9 +156,9 @@ const mobileLaunchProfile = {
|
|
|
157
156
|
if (mobileProvisioningBlocked(output)) {
|
|
158
157
|
return launch.fail(state, {
|
|
159
158
|
code: "MOBILE_PROVISION_REQUIRED",
|
|
160
|
-
message: `mobile ${
|
|
159
|
+
message: `mobile ${platformTarget ?? "runtime"} is not provisioned for this slot.`,
|
|
161
160
|
recoverable: false,
|
|
162
|
-
userAction: mobileProvisionCommand(target,
|
|
161
|
+
userAction: mobileProvisionCommand(target, platformTarget),
|
|
163
162
|
exitCode: EXIT.runtime,
|
|
164
163
|
originalError: output.trim() || void 0
|
|
165
164
|
});
|
|
@@ -177,14 +176,14 @@ const mobileLaunchProfile = {
|
|
|
177
176
|
},
|
|
178
177
|
recovery(_launch, output) {
|
|
179
178
|
const restartApp = mobileBridgeTargetMissing(output);
|
|
180
|
-
return { code: restartApp ? "mobile.app-restarted" :
|
|
179
|
+
return { code: restartApp ? "mobile.app-restarted" : METRO_RESTARTED, restartApp };
|
|
181
180
|
},
|
|
182
181
|
// Mobile proved its set inside launchMobile (null: nothing requested and no
|
|
183
182
|
// runtime answered).
|
|
184
183
|
provenFlags: (_launch, requested, proven) => ({ flags: proven === void 0 ? requested : proven }),
|
|
185
|
-
verifyArgs: ({
|
|
186
|
-
platformLabel: ({
|
|
187
|
-
deviceLabel: ({
|
|
184
|
+
verifyArgs: ({ platformTarget }) => platformTarget ? ["--platform", platformTarget] : [],
|
|
185
|
+
platformLabel: ({ platformTarget }) => platformTarget ?? null,
|
|
186
|
+
deviceLabel: ({ platformTarget }) => launchDeviceLabel(platformTarget),
|
|
188
187
|
evidence: metroLaunchEvidence
|
|
189
188
|
};
|
|
190
189
|
export {
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
bridgeCommand,
|
|
4
4
|
MOBILE_BRIDGE_ERROR_CODES
|
|
5
5
|
} from "../../../library/actions/mobile/platform/bridge.mjs";
|
|
6
|
-
import { resolveMobileToolPath } from "
|
|
6
|
+
import { resolveMobileToolPath } from "@farmslot/adapter-rn";
|
|
7
7
|
import {
|
|
8
8
|
MOBILE_LIFECYCLE_DEADLINE_FIELD,
|
|
9
9
|
MOBILE_LIFECYCLE_PREPARED
|
|
@@ -1,68 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
"SEGMENT_PROXY_URL",
|
|
8
|
-
"SEGMENT_WRITE_KEY",
|
|
9
|
-
"SEGMENT_FLUSH_INTERVAL",
|
|
10
|
-
"SEGMENT_FLUSH_EVENT_LIMIT"
|
|
11
|
-
];
|
|
1
|
+
import { metroEnvCheck, metroEnvFingerprint, recordMetroEnvBaseline } from "@farmslot/adapter-rn";
|
|
2
|
+
import { recipeRuntimePath } from "@farmslot/recipe-cli/harness";
|
|
3
|
+
const MOBILE_METRO_ENV_INPUTS = {
|
|
4
|
+
files: [".js.env", ".env", ".env.local"],
|
|
5
|
+
env: ["SEGMENT_PROXY_URL", "SEGMENT_WRITE_KEY", "SEGMENT_FLUSH_INTERVAL", "SEGMENT_FLUSH_EVENT_LIMIT"]
|
|
6
|
+
};
|
|
12
7
|
const BASELINE_FILE = "metro-env-baseline.json";
|
|
13
8
|
function mobileMetroEnvFingerprint(target) {
|
|
14
|
-
|
|
15
|
-
for (const relative of ENV_INPUTS) {
|
|
16
|
-
const absolute = path.join(target, relative);
|
|
17
|
-
hash.update(`${relative}\0`);
|
|
18
|
-
if (fs.existsSync(absolute)) hash.update(fs.readFileSync(absolute));
|
|
19
|
-
else hash.update("<absent>");
|
|
20
|
-
hash.update("\0");
|
|
21
|
-
}
|
|
22
|
-
for (const name of PROCESS_ENV_INPUTS) {
|
|
23
|
-
hash.update(`${name}\0${process.env[name] ?? "<absent>"}\0`);
|
|
24
|
-
}
|
|
25
|
-
return hash.digest("hex");
|
|
9
|
+
return metroEnvFingerprint(target, MOBILE_METRO_ENV_INPUTS);
|
|
26
10
|
}
|
|
27
11
|
function mobileMetroEnvCheck(target) {
|
|
28
|
-
|
|
29
|
-
const marker = readBaseline(target);
|
|
30
|
-
return {
|
|
31
|
-
fingerprint,
|
|
32
|
-
status: marker === null ? "missing" : marker.fingerprint === fingerprint ? "current" : "changed"
|
|
33
|
-
};
|
|
12
|
+
return metroEnvCheck(target, MOBILE_METRO_ENV_INPUTS, recipeRuntimePath(target, BASELINE_FILE));
|
|
34
13
|
}
|
|
35
14
|
function recordMobileMetroEnvBaseline(target, expectedFingerprint) {
|
|
36
|
-
|
|
37
|
-
const marker = recipeRuntimePath(target, BASELINE_FILE);
|
|
38
|
-
const temporary = `${marker}.${process.pid}.${Date.now()}.tmp`;
|
|
39
|
-
const baseline = {
|
|
40
|
-
schemaVersion: 1,
|
|
41
|
-
fingerprint: expectedFingerprint,
|
|
42
|
-
recordedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
43
|
-
};
|
|
44
|
-
fs.mkdirSync(path.dirname(marker), { recursive: true });
|
|
45
|
-
try {
|
|
46
|
-
fs.writeFileSync(temporary, `${JSON.stringify(baseline, null, 2)}
|
|
47
|
-
`, { mode: 384 });
|
|
48
|
-
if (mobileMetroEnvFingerprint(target) !== expectedFingerprint) return false;
|
|
49
|
-
fs.renameSync(temporary, marker);
|
|
50
|
-
if (mobileMetroEnvFingerprint(target) !== expectedFingerprint) {
|
|
51
|
-
if (readBaseline(target)?.fingerprint === expectedFingerprint) fs.rmSync(marker, { force: true });
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
} finally {
|
|
55
|
-
fs.rmSync(temporary, { force: true });
|
|
56
|
-
}
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
function readBaseline(target) {
|
|
60
|
-
try {
|
|
61
|
-
const parsed = JSON.parse(fs.readFileSync(recipeRuntimePath(target, BASELINE_FILE), "utf8"));
|
|
62
|
-
return parsed.schemaVersion === 1 && typeof parsed.fingerprint === "string" ? parsed : null;
|
|
63
|
-
} catch {
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
15
|
+
return recordMetroEnvBaseline(target, MOBILE_METRO_ENV_INPUTS, recipeRuntimePath(target, BASELINE_FILE), expectedFingerprint);
|
|
66
16
|
}
|
|
67
17
|
export {
|
|
68
18
|
mobileMetroEnvCheck,
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import brokerModule from "@farmslot/recipe-runner/cdp-broker";
|
|
3
|
+
import configModule from "@farmslot/adapter-rn/bridge-runtime/lib/config.cjs";
|
|
4
|
+
const { brokerSocketPath, createBrokerClient } = brokerModule;
|
|
5
|
+
const { resolvePort } = configModule;
|
|
6
|
+
async function createMobileNetworkBackend(target, env) {
|
|
7
|
+
const { client } = await connectMobileBroker(target, env);
|
|
8
|
+
return {
|
|
9
|
+
start(params) {
|
|
10
|
+
return client.control("capture-start", params, 1e4);
|
|
11
|
+
},
|
|
12
|
+
async end(id) {
|
|
13
|
+
return asRecord(await client.control("capture-end", { id }, 1e4));
|
|
14
|
+
},
|
|
15
|
+
async close() {
|
|
16
|
+
client.close();
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
async function connectMobileBroker(target, env) {
|
|
21
|
+
const runtimeDir = env.RECIPE_RUNTIME_DIR ? path.resolve(target, env.RECIPE_RUNTIME_DIR) : path.join(target, "temp", "recipe", "runtime");
|
|
22
|
+
const socketPath = brokerSocketPath(
|
|
23
|
+
runtimeDir,
|
|
24
|
+
resolvePort(env, target)
|
|
25
|
+
);
|
|
26
|
+
const discoveryClient = await createBrokerClient(socketPath, "", 1e4);
|
|
27
|
+
let targets;
|
|
28
|
+
try {
|
|
29
|
+
targets = await discoveryClient.control(
|
|
30
|
+
"resolve-targets",
|
|
31
|
+
{ nameIncludes: mobileTargetPin(env) },
|
|
32
|
+
1e4
|
|
33
|
+
);
|
|
34
|
+
} finally {
|
|
35
|
+
discoveryClient.close();
|
|
36
|
+
}
|
|
37
|
+
const deviceId = selectMobileBrokerTarget(targets, env);
|
|
38
|
+
const client = await createBrokerClient(socketPath, deviceId, 1e4);
|
|
39
|
+
return { client, deviceId };
|
|
40
|
+
}
|
|
41
|
+
function selectMobileBrokerTarget(value, env) {
|
|
42
|
+
const targets = Array.isArray(value) ? value.map(asRecord).filter((target) => target.deviceId) : [];
|
|
43
|
+
const pin = mobileTargetPin(env);
|
|
44
|
+
const candidates = pin ? targets.filter(
|
|
45
|
+
(target) => String(target.name ?? "").toLowerCase().includes(pin.toLowerCase())
|
|
46
|
+
) : targets;
|
|
47
|
+
if (candidates.length !== 1) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
`Mobile network observation requires one broker target; found ${candidates.length}.`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return String(candidates[0].deviceId);
|
|
53
|
+
}
|
|
54
|
+
function mobileTargetPin(env) {
|
|
55
|
+
const platform = String(
|
|
56
|
+
env.RECIPE_RN_EXPLICIT_PLATFORM ?? env.RECIPE_HARNESS_PLATFORM ?? ""
|
|
57
|
+
).toLowerCase();
|
|
58
|
+
return String(
|
|
59
|
+
platform === "android" ? env.ANDROID_TARGET_DEVICE_NAME ?? env.ANDROID_DEVICE ?? "" : platform === "ios" ? env.IOS_SIMULATOR ?? "" : env.IOS_SIMULATOR ?? env.ANDROID_TARGET_DEVICE_NAME ?? env.ANDROID_DEVICE ?? ""
|
|
60
|
+
).trim();
|
|
61
|
+
}
|
|
62
|
+
function asRecord(value) {
|
|
63
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
connectMobileBroker,
|
|
67
|
+
createMobileNetworkBackend
|
|
68
|
+
};
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createCdpTraceCollector
|
|
3
3
|
} from "../performance/cdp-trace.js";
|
|
4
|
-
import {
|
|
5
|
-
connectMobileBroker
|
|
6
|
-
} from "../../network-observation.js";
|
|
4
|
+
import { connectMobileBroker } from "./network-observer.js";
|
|
7
5
|
import { createAndroidGfxinfoPerformanceBackend } from "./android-gfxinfo-performance.js";
|
|
8
6
|
async function createMobilePerformanceBackend(target, env) {
|
|
9
7
|
if (resolvePlatform(env) === "android") {
|
|
@@ -37,7 +35,7 @@ async function markRuntime(client, name) {
|
|
|
37
35
|
}
|
|
38
36
|
function resolvePlatform(env) {
|
|
39
37
|
const explicit = String(
|
|
40
|
-
env.
|
|
38
|
+
env.RECIPE_RN_EXPLICIT_PLATFORM ?? env.RECIPE_HARNESS_PLATFORM ?? ""
|
|
41
39
|
).toLowerCase();
|
|
42
40
|
if (explicit === "android" || explicit === "ios") return explicit;
|
|
43
41
|
return env.ADB_SERIAL || env.ANDROID_SERIAL || env.ANDROID_DEVICE ? "android" : "ios";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { recipeRuntimeDir } from "
|
|
3
|
+
import { recipeRuntimeDir } from "@farmslot/recipe-cli/harness";
|
|
4
4
|
function readRuntimeContextTarget(target) {
|
|
5
5
|
const file = path.join(target, recipeRuntimeDir(), "agentic-runtime.json");
|
|
6
6
|
let parsed;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
+
import { EXIT, spawnScriptStreaming, shellQuote } from "@farmslot/recipe-cli/harness";
|
|
1
2
|
import { execFileSync } from "node:child_process";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { recordDepsBaseline } from "@farmslot/recipe-runner/runtime/deps-readiness";
|
|
4
|
-
import { resolveAndExportMobileToolPaths } from "
|
|
5
|
-
import { EXIT, spawnScriptStreaming } from "../../commands/shared.js";
|
|
6
|
-
import { shellQuote } from "../../commands/parse-args.js";
|
|
5
|
+
import { resolveAndExportMobileToolPaths } from "@farmslot/adapter-rn";
|
|
7
6
|
import { runnerDir } from "../../paths.js";
|
|
8
7
|
import {
|
|
9
8
|
decideMobileReadiness,
|
|
@@ -401,7 +400,7 @@ async function dispatchAction(action, target, platform, json, preflightMode = "f
|
|
|
401
400
|
leaf,
|
|
402
401
|
withWatcherPort(["--target", cwd, ...extra], watcherPort),
|
|
403
402
|
target,
|
|
404
|
-
{
|
|
403
|
+
{ RECIPE_RN_METRO_ENV_FINGERPRINT: metroEnvFingerprint ?? mobileMetroEnvCheck(path.resolve(target)).fingerprint }
|
|
405
404
|
);
|
|
406
405
|
}
|
|
407
406
|
case "start-console-forwarder": {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { recipeRuntimeDir } from "@farmslot/recipe-cli/harness";
|
|
1
2
|
import { execFileSync } from "node:child_process";
|
|
2
3
|
import crypto from "node:crypto";
|
|
3
4
|
import fs from "node:fs";
|
|
4
5
|
import os from "node:os";
|
|
5
6
|
import path from "node:path";
|
|
6
|
-
import { recipeRuntimeDir } from "../../paths.js";
|
|
7
7
|
import { resolveSlotPortsByRepo } from "../../../adapters/shared/resolve-slot-ports-core.mjs";
|
|
8
8
|
const RUNWAY_IOS_METADATA = {
|
|
9
9
|
artifactName: "ios-app-main-dev-expo",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { optionFlag, optionString, parsePort } from "
|
|
1
|
+
import { optionFlag, optionString, parsePort } from "@farmslot/recipe-cli/harness";
|
|
2
2
|
import { detectOrphanMetros, mobileToolDoctorChecks } from "./doctor-checks.js";
|
|
3
3
|
import { ensureMobilePerpsEnvironment, mobilePerpsEnvironment } from "./perps-env.js";
|
|
4
4
|
const mobileReadiness = {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function resolveAndroidDeviceSerial(env = process.env) {
|
|
2
|
+
return env.ADB_SERIAL?.trim() || process.env.ADB_SERIAL?.trim() || void 0;
|
|
3
|
+
}
|
|
4
|
+
function resolveMobileIosSimulatorName(env = process.env) {
|
|
5
|
+
const explicit = env.IOS_SIMULATOR?.trim() || env.SIM_UDID?.trim();
|
|
6
|
+
if (explicit) return explicit;
|
|
7
|
+
const slot = env.FARMSLOT_SLOT_ID?.trim() || env.SLOT_ID?.trim();
|
|
8
|
+
if (!slot) return void 0;
|
|
9
|
+
const suffix = slot.includes("-") ? slot.slice(slot.lastIndexOf("-") + 1) : slot;
|
|
10
|
+
return suffix || void 0;
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
resolveAndroidDeviceSerial,
|
|
14
|
+
resolveMobileIosSimulatorName
|
|
15
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { recipeRuntimePath } from "@farmslot/recipe-cli/harness";
|
|
1
2
|
import { randomBytes } from "node:crypto";
|
|
2
3
|
import fs from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
|
-
import { recipeRuntimePath } from "../../paths.js";
|
|
5
5
|
import {
|
|
6
6
|
assertAndroidReleaseArtifactRuntime
|
|
7
7
|
} from "./release-artifact.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { EXIT, spawnScript } from "@farmslot/recipe-cli/harness";
|
|
1
2
|
import path from "node:path";
|
|
2
|
-
import { EXIT, spawnScript } from "../../commands/shared.js";
|
|
3
3
|
import { runnerDir } from "../../paths.js";
|
|
4
4
|
function reloadMobile(target, json) {
|
|
5
5
|
const script = path.join(runnerDir, "adapters/mobile/reload-app.mjs");
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
+
import { EXIT, isRecord } from "@farmslot/recipe-cli/harness";
|
|
1
2
|
import { spawnSync } from "node:child_process";
|
|
2
3
|
import path from "node:path";
|
|
3
|
-
import {
|
|
4
|
+
import { IOS_SIMULATOR_RECORDING_TARGET_PREFIX } from "@farmslot/adapter-rn";
|
|
4
5
|
import { runnerDir } from "../../paths.js";
|
|
5
6
|
import { devicePlatformFromEnv } from "../performance/device-platform.js";
|
|
6
7
|
import {
|
|
7
|
-
IOS_SIMULATOR_RECORDING_TARGET_PREFIX,
|
|
8
8
|
resolveAndroidDeviceSerial,
|
|
9
9
|
resolveMobileIosSimulatorName
|
|
10
|
-
} from "
|
|
10
|
+
} from "./recording-target.js";
|
|
11
|
+
import { emitProofFailure } from "../proof-failure.js";
|
|
12
|
+
import { mobileAppIdentityEnv } from "./app-identity.js";
|
|
11
13
|
import { requireCurrentMobileReleaseArtifactState } from "./release-artifact-state.js";
|
|
12
14
|
const EXPLICIT_DEVICE_KEYS = [
|
|
13
15
|
"PLATFORM",
|
|
14
|
-
"
|
|
16
|
+
"RECIPE_RN_EXPLICIT_PLATFORM",
|
|
15
17
|
"IOS_SIMULATOR",
|
|
16
18
|
"SIM_UDID",
|
|
17
19
|
"ADB_SERIAL",
|
|
@@ -21,7 +23,7 @@ const EXPLICIT_DEVICE_KEYS = [
|
|
|
21
23
|
];
|
|
22
24
|
const mobileRun = {
|
|
23
25
|
pinnedEnv() {
|
|
24
|
-
if (!process.env.
|
|
26
|
+
if (!process.env.RECIPE_RN_EXPLICIT_PLATFORM) return void 0;
|
|
25
27
|
return Object.fromEntries(EXPLICIT_DEVICE_KEYS.map((key) => [key, process.env[key]]));
|
|
26
28
|
},
|
|
27
29
|
envKeys: ["METAMASK_RECIPE_MOBILE_OPAQUE_RUNTIME", "ANDROID_PACKAGE_ID", "ADB_SERIAL", "ANDROID_SERIAL"],
|
|
@@ -49,8 +51,11 @@ const mobileRun = {
|
|
|
49
51
|
ANDROID_TARGET_DEVICE_NAME: process.env.ANDROID_TARGET_DEVICE_NAME,
|
|
50
52
|
ADB_SERIAL: process.env.ADB_SERIAL,
|
|
51
53
|
ANDROID_SERIAL: process.env.ANDROID_SERIAL,
|
|
52
|
-
|
|
53
|
-
METAMASK_RECIPE_MOBILE_OPAQUE_RUNTIME: process.env.METAMASK_RECIPE_MOBILE_OPAQUE_RUNTIME
|
|
54
|
+
...mobileAppIdentityEnv(),
|
|
55
|
+
METAMASK_RECIPE_MOBILE_OPAQUE_RUNTIME: process.env.METAMASK_RECIPE_MOBILE_OPAQUE_RUNTIME,
|
|
56
|
+
// The platform `--platform`/`--device` pinned; the React Native bridge
|
|
57
|
+
// matches its target against it.
|
|
58
|
+
RECIPE_RN_EXPLICIT_PLATFORM: process.env.RECIPE_RN_EXPLICIT_PLATFORM
|
|
54
59
|
}),
|
|
55
60
|
// An installed release artifact is opaque: no harness HUD inside it.
|
|
56
61
|
autoHud: () => process.env.METAMASK_RECIPE_MOBILE_OPAQUE_RUNTIME !== "1",
|
|
@@ -64,12 +69,28 @@ const mobileRun = {
|
|
|
64
69
|
// source only matters for a development build the caller did not restart.
|
|
65
70
|
runtimeCheck({ target, heal, state, json, appRestartAuthored }) {
|
|
66
71
|
if (requireCurrentMobileReleaseArtifactState(target) !== null || appRestartAuthored) return void 0;
|
|
67
|
-
return
|
|
68
|
-
const { ensureMobileProofRuntime } = await import("../../commands/run-engine.js");
|
|
69
|
-
return ensureMobileProofRuntime(target, heal, state, json);
|
|
70
|
-
};
|
|
72
|
+
return () => ensureMobileProofRuntime(target, heal, state, json);
|
|
71
73
|
}
|
|
72
74
|
};
|
|
75
|
+
async function ensureMobileProofRuntime(target, _heal, state, json, deps = {}) {
|
|
76
|
+
const source = await import("./source-freshness.js");
|
|
77
|
+
const check = deps.check ?? (() => source.mobileSourceCheck(target));
|
|
78
|
+
const initial = check();
|
|
79
|
+
if (initial.status === "unavailable") {
|
|
80
|
+
emitProofFailure(json, { recoverable: false, error: initial.error });
|
|
81
|
+
return EXIT.usage;
|
|
82
|
+
}
|
|
83
|
+
if (initial.status === "current") return null;
|
|
84
|
+
const targetArg = JSON.stringify(path.resolve(target));
|
|
85
|
+
const userAction = `mm-harness call app.lifecycle --arg command=restart --adapter mobile --target ${targetArg}`;
|
|
86
|
+
const message = `Mobile loaded source is not current (${initial.status}).`;
|
|
87
|
+
emitProofFailure(json, {
|
|
88
|
+
recoverable: true,
|
|
89
|
+
mutations: state.mutations,
|
|
90
|
+
error: { code: "MOBILE_SOURCE_NOT_LOADED", message, userAction }
|
|
91
|
+
});
|
|
92
|
+
return EXIT.infra;
|
|
93
|
+
}
|
|
73
94
|
const mobileRecording = {
|
|
74
95
|
target: (context) => resolveMobileRecordingTarget(context),
|
|
75
96
|
// An Android device records through the mirror, with screenrecord as the
|
|
@@ -78,7 +99,7 @@ const mobileRecording = {
|
|
|
78
99
|
const androidSerial = resolveAndroidDeviceSerial();
|
|
79
100
|
const iosSimulator = androidSerial ? void 0 : resolveMobileIosSimulatorName();
|
|
80
101
|
if (!androidSerial && !iosSimulator) return void 0;
|
|
81
|
-
const { createAndroidVideoRecorder, createIosSimulatorVideoRecorder } = await import("
|
|
102
|
+
const { createAndroidVideoRecorder, createIosSimulatorVideoRecorder } = await import("@farmslot/adapter-rn");
|
|
82
103
|
if (androidSerial) {
|
|
83
104
|
const { createAndroidMirrorVideoRecorder } = await import("@farmslot/recipe-runner");
|
|
84
105
|
return createAndroidMirrorVideoRecorder({ serial: androidSerial, fallback: createAndroidVideoRecorder(androidSerial) });
|
|
@@ -126,11 +147,13 @@ const mobileDiagnostics = {
|
|
|
126
147
|
};
|
|
127
148
|
const mobileObservation = {
|
|
128
149
|
network: {
|
|
129
|
-
backend: async (target, env) => (await import("
|
|
150
|
+
backend: async (target, env) => (await import("./network-observer.js")).createMobileNetworkBackend(target, env)
|
|
130
151
|
},
|
|
131
152
|
performance: {
|
|
132
|
-
|
|
133
|
-
|
|
153
|
+
start: async (context) => (await import("../../performance-observation.js")).startRunPerformanceObservation({
|
|
154
|
+
backend: async (target, env) => (await import("./performance-observer.js")).createMobilePerformanceBackend(target, env),
|
|
155
|
+
platform: (env) => devicePlatformFromEnv(env)
|
|
156
|
+
}, context)
|
|
134
157
|
}
|
|
135
158
|
};
|
|
136
159
|
function runMobileIssueCommand(projectRoot, command) {
|
|
@@ -149,6 +172,7 @@ function runMobileIssueCommand(projectRoot, command) {
|
|
|
149
172
|
}
|
|
150
173
|
}
|
|
151
174
|
export {
|
|
175
|
+
ensureMobileProofRuntime,
|
|
152
176
|
mobileDiagnostics,
|
|
153
177
|
mobileObservation,
|
|
154
178
|
mobileRecording,
|
|
@@ -11,10 +11,8 @@ import {
|
|
|
11
11
|
supersededErrorCapture
|
|
12
12
|
} from "@farmslot/recipe-runner/runtime/log-analysis";
|
|
13
13
|
import { probeMetroPackager } from "@farmslot/recipe-runner/runtime/metro-probe";
|
|
14
|
-
import { color } from "
|
|
15
|
-
import {
|
|
16
|
-
import { recipeRuntimePath } from "../../paths.js";
|
|
17
|
-
import { resolveMobileToolPath } from "../../../library/actions/mobile/platform/tool-paths.mjs";
|
|
14
|
+
import { color, recipeRuntimePath, shellQuote } from "@farmslot/recipe-cli/harness";
|
|
15
|
+
import { resolveMobileToolPath } from "@farmslot/adapter-rn";
|
|
18
16
|
import { mobileProductMarkers } from "./deps-markers.js";
|
|
19
17
|
import { mobileMetroEnvCheck } from "./metro-env.js";
|
|
20
18
|
const BUNDLE_ERR = /Bundling failed|Unable to resolve /u;
|