@deeeed/metamask-harness 0.79.0 → 0.80.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 +47 -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 +2 -34
- 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/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 +4 -3
- 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/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 +1 -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 +24 -10
- 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/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/performance-observer.js +1 -1
- 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 +8 -7
- 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/slot-ports.js +1 -1
- package/dist/adapters/surface.js +1 -0
- package/dist/adapters/terminal/console-capture.js +1 -1
- package/dist/adapters/terminal/launch.js +1 -1
- package/dist/adapters/terminal/run.js +25 -2
- package/dist/adapters/terminal/surface.js +7 -1
- package/dist/adapters.js +8 -4
- package/dist/advisor-policy.js +1 -1
- package/dist/checkout-view.js +1 -2
- package/dist/cli.js +28 -15
- package/dist/command-contract.js +1 -26
- package/dist/commands/call.js +10 -24
- package/dist/commands/check.js +3 -4
- package/dist/commands/checklist.js +1 -1
- package/dist/commands/completion-candidates.js +2 -10
- 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/list-executables.js +1 -3
- package/dist/commands/logs.js +3 -3
- package/dist/commands/manifest.js +1 -12
- 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/run-engine.js +12 -51
- package/dist/commands/run.js +4 -25
- 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 +2 -6
- 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/funding-execution-context.js +15 -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 +2 -4
- package/dist/network-observation.js +4 -4
- package/dist/paths.js +34 -64
- package/dist/performance-observation.js +2 -2
- package/dist/progress.js +1 -1
- package/dist/recipe-assistance-context.js +1 -3
- package/dist/recipe-security.js +2 -59
- package/dist/review/knowledge.js +2 -2
- package/dist/runner.js +5 -3
- package/dist/runtime-context.js +1 -1
- package/dist/task-view.js +2 -3
- package/docs/CONTRIBUTING.md +1 -1
- 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 -130
- package/library/actions/core/perps/quote_fees.mjs +58 -0
- package/library/actions/core/wallet/_fixture-accounts.mjs +69 -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/platform/cdp.mjs +2 -8
- package/library/actions/harness-exports.mjs +1 -6
- package/library/actions/mobile/app/network-control.mjs +6 -8
- 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/terminal/platform/runtime.mjs +2 -1
- package/library/manifests/core.action-manifest.json +83 -13
- package/package.json +8 -9
- 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/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/last.js +0 -60
- package/dist/commands/launch/index.js +0 -109
- package/dist/commands/parse-args.js +0 -279
- package/dist/commands/reload.js +0 -41
- package/dist/commands/run-report.js +0 -241
- package/dist/commands/shared.js +0 -323
- package/dist/commands/stop.js +0 -60
- package/dist/devices.js +0 -100
- 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/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
package/dist/harness.js
DELETED
|
@@ -1,451 +0,0 @@
|
|
|
1
|
-
import { spawnScriptStreaming } from "./commands/shared.js";
|
|
2
|
-
import { execFileSync } from "node:child_process";
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { shellLeafMissing, missingShellLeafMessage } from "./leaf-invoke.js";
|
|
6
|
-
import { adapterRegistry } from "./adapters/registry.js";
|
|
7
|
-
import { recipeHarnessPath, recipeRuntimeDir, runnerDir } from "./paths.js";
|
|
8
|
-
import { colorHumanMessage } from "./cli-color.js";
|
|
9
|
-
const HARNESS_ACTIONS = ["install", "verify", "cleanup"];
|
|
10
|
-
const ADAPTERS = ["mobile", "extension", "core", "terminal"];
|
|
11
|
-
function harnessUsage() {
|
|
12
|
-
console.error(`mm-harness \u2014 install and validate the MetaMask recipe runtime in a checkout.
|
|
13
|
-
|
|
14
|
-
Run it from inside a MetaMask checkout; the platform (mobile | extension | core | terminal)
|
|
15
|
-
is auto-detected from the repo. Pass --platform only to override.
|
|
16
|
-
|
|
17
|
-
Commands (one copy-pasteable example each):
|
|
18
|
-
install Install the recipe harness runtime overlay into the checkout.
|
|
19
|
-
mm-harness install
|
|
20
|
-
verify Check the harness/runtime is present and healthy (no app launch).
|
|
21
|
-
mm-harness verify
|
|
22
|
-
cleanup Remove the installed harness overlay and restore the checkout.
|
|
23
|
-
mm-harness cleanup
|
|
24
|
-
|
|
25
|
-
Options:
|
|
26
|
-
--platform <mobile|extension|core|terminal> Override auto-detection (alias: --adapter).
|
|
27
|
-
--target <repo> Checkout to operate on (default: current dir).
|
|
28
|
-
--json Machine-readable summary for agents/scripts.
|
|
29
|
-
-- <args> Forward the rest verbatim to the underlying
|
|
30
|
-
script, e.g. -- --platform ios --preflight-mode fast
|
|
31
|
-
(mobile) or -- --cdp-port 6665 (extension).
|
|
32
|
-
|
|
33
|
-
Examples:
|
|
34
|
-
mm-harness install # inside a checkout, auto-detected
|
|
35
|
-
mm-harness verify --platform extension
|
|
36
|
-
mm-harness cleanup --target ../metamask-mobile
|
|
37
|
-
|
|
38
|
-
core supports install, verify, and cleanup (headless; no live).`);
|
|
39
|
-
}
|
|
40
|
-
function failureHint(surface, action) {
|
|
41
|
-
const restart = surface.harness.restart;
|
|
42
|
-
if (!restart) {
|
|
43
|
-
if (action === "verify") {
|
|
44
|
-
return `Install the ${surface.id} harness first: mm-harness install --platform ${surface.id}`;
|
|
45
|
-
}
|
|
46
|
-
return "Read the error above for the specific cause, then re-run this command.";
|
|
47
|
-
}
|
|
48
|
-
return `Read the error above for the specific cause. To (re)start the runtime, run: ${restart}`;
|
|
49
|
-
}
|
|
50
|
-
function successNext(adapter, action, target) {
|
|
51
|
-
const base = `--adapter ${adapter} --target ${shellQuote(target)}`;
|
|
52
|
-
if (action === "install") return `mm-harness verify ${base}`;
|
|
53
|
-
if (action === "cleanup") return `mm-harness install ${base}`;
|
|
54
|
-
return `mm-harness status --target ${shellQuote(target)} --json`;
|
|
55
|
-
}
|
|
56
|
-
function hasArg(args, needle) {
|
|
57
|
-
return args.some((arg) => arg === needle || arg.startsWith(`${needle}=`));
|
|
58
|
-
}
|
|
59
|
-
function argValue(args, needle) {
|
|
60
|
-
for (let i = 0; i < args.length; i += 1) {
|
|
61
|
-
if (args[i] === needle) return args[i + 1];
|
|
62
|
-
if (args[i].startsWith(`${needle}=`)) return args[i].slice(needle.length + 1);
|
|
63
|
-
}
|
|
64
|
-
return void 0;
|
|
65
|
-
}
|
|
66
|
-
function shellQuote(value) {
|
|
67
|
-
return /^[A-Za-z0-9_./:=@+-]+$/u.test(value) ? value : `'${value.replace(/'/gu, `'\\''`)}'`;
|
|
68
|
-
}
|
|
69
|
-
function isAdapter(value) {
|
|
70
|
-
return value !== void 0 && adapterRegistry.has(value);
|
|
71
|
-
}
|
|
72
|
-
function parseHarnessArgs(args) {
|
|
73
|
-
const forward = [];
|
|
74
|
-
let adapter;
|
|
75
|
-
let json = false;
|
|
76
|
-
let quiet = false;
|
|
77
|
-
let separator = false;
|
|
78
|
-
for (let i = 0; i < args.length; i += 1) {
|
|
79
|
-
const arg = args[i];
|
|
80
|
-
if (separator) {
|
|
81
|
-
forward.push(arg);
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
if (arg === "--") {
|
|
85
|
-
separator = true;
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
if (arg === "--json") {
|
|
89
|
-
json = true;
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
if (arg === "--quiet") {
|
|
93
|
-
quiet = true;
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
if (arg === "--adapter" || arg === "--platform") {
|
|
97
|
-
const value = args[i + 1];
|
|
98
|
-
if (arg === "--adapter") {
|
|
99
|
-
adapter = value;
|
|
100
|
-
i += 1;
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
if (adapter === void 0 && isAdapter(value)) {
|
|
104
|
-
adapter = value;
|
|
105
|
-
i += 1;
|
|
106
|
-
continue;
|
|
107
|
-
}
|
|
108
|
-
forward.push(arg);
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
if (arg.startsWith("--adapter=")) {
|
|
112
|
-
adapter = arg.slice("--adapter=".length);
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
if (arg.startsWith("--platform=")) {
|
|
116
|
-
const value = arg.slice("--platform=".length);
|
|
117
|
-
if (adapter === void 0 && isAdapter(value)) {
|
|
118
|
-
adapter = value;
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
|
-
forward.push(arg);
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
forward.push(arg);
|
|
125
|
-
}
|
|
126
|
-
return { adapter, json, quiet, forward };
|
|
127
|
-
}
|
|
128
|
-
const ADAPTER_DETECT_NEXT = "cd into a MetaMask checkout or pass --target <path>, or force it with --adapter <mobile|extension|core|terminal>";
|
|
129
|
-
function detectAdapter(target) {
|
|
130
|
-
let remote = "";
|
|
131
|
-
try {
|
|
132
|
-
remote = execFileSync("git", ["-C", target, "config", "--get", "remote.origin.url"], {
|
|
133
|
-
encoding: "utf8",
|
|
134
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
135
|
-
}).trim();
|
|
136
|
-
} catch {
|
|
137
|
-
remote = "";
|
|
138
|
-
}
|
|
139
|
-
if (remote.includes("metamask-extension")) return "extension";
|
|
140
|
-
if (remote.includes("metamask-mobile")) return "mobile";
|
|
141
|
-
const exists = (rel) => fs.existsSync(path.join(target, rel));
|
|
142
|
-
const isDir = (rel) => {
|
|
143
|
-
try {
|
|
144
|
-
return fs.statSync(path.join(target, rel)).isDirectory();
|
|
145
|
-
} catch {
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
if (exists("development/skills-sync.ts") || isDir("ui") && isDir("app/scripts")) return "extension";
|
|
150
|
-
if (exists("scripts/skills-sync.mts") || isDir("ios") && isDir("android") && isDir("app/core")) return "mobile";
|
|
151
|
-
if (isDir("packages/perps-controller") && exists("yarn.lock")) return "core";
|
|
152
|
-
if (remote.includes("va-mmcx-terminal") || isDir("src/features/perpetuals") && (exists("next.config.ts") || exists("next.config.mjs") || exists("next.config.js"))) return "terminal";
|
|
153
|
-
return void 0;
|
|
154
|
-
}
|
|
155
|
-
function resolveRuntimeContextPath(target) {
|
|
156
|
-
return process.env.RECIPE_RUNTIME_CONTEXT ?? path.join(target, recipeRuntimeDir(), "agentic-runtime.json");
|
|
157
|
-
}
|
|
158
|
-
function readRuntimeContextField(contextPath, field) {
|
|
159
|
-
let data;
|
|
160
|
-
try {
|
|
161
|
-
data = JSON.parse(fs.readFileSync(contextPath, "utf8"));
|
|
162
|
-
} catch {
|
|
163
|
-
return void 0;
|
|
164
|
-
}
|
|
165
|
-
let node = data;
|
|
166
|
-
for (const key of field.split(".")) {
|
|
167
|
-
if (node === void 0 || node === null || typeof node !== "object") return void 0;
|
|
168
|
-
node = node[key];
|
|
169
|
-
}
|
|
170
|
-
if (node === void 0 || node === null || node === "") return void 0;
|
|
171
|
-
return String(node);
|
|
172
|
-
}
|
|
173
|
-
function resolveEntry(base, candidates, mode) {
|
|
174
|
-
for (const candidate of candidates) {
|
|
175
|
-
const full = path.resolve(base, candidate);
|
|
176
|
-
try {
|
|
177
|
-
const stat = fs.statSync(full);
|
|
178
|
-
if (!stat.isFile()) continue;
|
|
179
|
-
if (mode === "file" || (stat.mode & 73) !== 0) return full;
|
|
180
|
-
} catch {
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
return path.resolve(base, candidates[0]);
|
|
184
|
-
}
|
|
185
|
-
function installedRunnerSource(target, adapter) {
|
|
186
|
-
const pointer = path.join(recipeHarnessPath(target, adapter), "runner", ".runner-source");
|
|
187
|
-
if (!fs.existsSync(pointer)) return void 0;
|
|
188
|
-
const value = fs.readFileSync(pointer, "utf8").trim();
|
|
189
|
-
if (!value || !fs.existsSync(value)) return void 0;
|
|
190
|
-
return value;
|
|
191
|
-
}
|
|
192
|
-
function resolveHarnessDispatch(surface, action, target) {
|
|
193
|
-
if (action === "verify") return surface.harness.verify(target);
|
|
194
|
-
const leaf = action === "install" ? surface.harness.install : surface.harness.cleanup;
|
|
195
|
-
const base = action === "cleanup" && surface.harness.cleanup.fromInstalledRunner ? installedRunnerSource(target, surface.id) ?? runnerDir : runnerDir;
|
|
196
|
-
const entry = resolveEntry(base, [leaf.entry, leaf.fallback], "file");
|
|
197
|
-
return leaf.node ? { command: process.execPath, prefixArgs: [entry] } : { command: entry, prefixArgs: [] };
|
|
198
|
-
}
|
|
199
|
-
async function handleHarness(argv) {
|
|
200
|
-
const action = argv[0];
|
|
201
|
-
if (!action || action === "-h" || action === "--help") {
|
|
202
|
-
harnessUsage();
|
|
203
|
-
return action ? 0 : 2;
|
|
204
|
-
}
|
|
205
|
-
if (!HARNESS_ACTIONS.includes(action)) {
|
|
206
|
-
harnessUsage();
|
|
207
|
-
console.error(`unsupported harness subcommand: ${action}`);
|
|
208
|
-
return 2;
|
|
209
|
-
}
|
|
210
|
-
const harnessAction = action;
|
|
211
|
-
const { getAdapterSurface } = await import("./adapters/surface.js");
|
|
212
|
-
const { adapter: parsedAdapter, json, quiet, forward } = parseHarnessArgs(argv.slice(1));
|
|
213
|
-
const rawTarget = argValue(forward, "--target");
|
|
214
|
-
const target = path.resolve(rawTarget ?? process.cwd());
|
|
215
|
-
const adapter = parsedAdapter ?? detectAdapter(target);
|
|
216
|
-
if (!adapter || !isAdapter(adapter)) {
|
|
217
|
-
if (quiet) {
|
|
218
|
-
return 2;
|
|
219
|
-
} else if (json) {
|
|
220
|
-
const detectError = adapter ? { code: "UNSUPPORTED_PLATFORM", message: `unsupported platform: ${adapter}`, userAction: "pass --adapter <mobile|extension|core|terminal> to specify a supported adapter" } : { code: "ADAPTER_DETECTION_FAILED", message: `could not detect the MetaMask repo type for ${target}`, userAction: ADAPTER_DETECT_NEXT };
|
|
221
|
-
console.log(harnessSummary(harnessAction, void 0, target, "fail", 2, false, detectError));
|
|
222
|
-
} else {
|
|
223
|
-
harnessUsage();
|
|
224
|
-
console.error(
|
|
225
|
-
adapter ? `
|
|
226
|
-
\u2717 unsupported platform: ${adapter}` : `
|
|
227
|
-
\u2717 could not detect the MetaMask repo type for ${target}
|
|
228
|
-
Next: ${ADAPTER_DETECT_NEXT}`
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
return 2;
|
|
232
|
-
}
|
|
233
|
-
const autoDetected = parsedAdapter === void 0;
|
|
234
|
-
let forwardArgs = hasArg(forward, "--target") ? [...forward] : ["--target", target, ...forward];
|
|
235
|
-
if (harnessAction === "install" && hasArg(forward, "--runway")) {
|
|
236
|
-
return handleRunwayInstall(adapter, target, forward, json);
|
|
237
|
-
}
|
|
238
|
-
const surface = getAdapterSurface(adapter);
|
|
239
|
-
if (harnessAction === "verify" && surface.harness.verifyArgs) {
|
|
240
|
-
forwardArgs = surface.harness.verifyArgs(target, forwardArgs);
|
|
241
|
-
}
|
|
242
|
-
const dispatch = resolveHarnessDispatch(surface, harnessAction, target);
|
|
243
|
-
if ("error" in dispatch) {
|
|
244
|
-
if (quiet) {
|
|
245
|
-
return 1;
|
|
246
|
-
} else if (json) {
|
|
247
|
-
console.log(
|
|
248
|
-
harnessSummary(harnessAction, adapter, target, "fail", 1, autoDetected, {
|
|
249
|
-
code: "DISPATCH_UNAVAILABLE",
|
|
250
|
-
message: dispatch.error,
|
|
251
|
-
// The dispatch error embeds "Next: <hint>" — extract it so --json consumers
|
|
252
|
-
// get a clean programmatic escape without parsing the human message.
|
|
253
|
-
userAction: dispatch.error.split("\nNext: ")[1] ?? "run mm-harness install to complete setup, then retry"
|
|
254
|
-
})
|
|
255
|
-
);
|
|
256
|
-
} else {
|
|
257
|
-
console.error(`\u2717 ${harnessAction} ${adapter} failed
|
|
258
|
-
${dispatch.error.replace(/\n/gu, "\n ")}`);
|
|
259
|
-
}
|
|
260
|
-
return 1;
|
|
261
|
-
}
|
|
262
|
-
if (!json && !quiet) {
|
|
263
|
-
const detected = autoDetected ? ", auto-detected" : "";
|
|
264
|
-
console.error(colorHumanMessage(`\u2192 ${harnessAction} (${adapter}${detected}) \u2014 target: ${target}`));
|
|
265
|
-
}
|
|
266
|
-
const start = Date.now();
|
|
267
|
-
if ("inProcess" in dispatch) {
|
|
268
|
-
const runVerify = await dispatch.inProcess();
|
|
269
|
-
let exitCode;
|
|
270
|
-
try {
|
|
271
|
-
exitCode = await runVerify(forwardArgs, {
|
|
272
|
-
out: quiet ? () => {
|
|
273
|
-
} : (line) => {
|
|
274
|
-
(json ? process.stderr : process.stdout).write(`${line}
|
|
275
|
-
`);
|
|
276
|
-
},
|
|
277
|
-
err: quiet ? () => {
|
|
278
|
-
} : (line) => {
|
|
279
|
-
process.stderr.write(`${line}
|
|
280
|
-
`);
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
} catch (error) {
|
|
284
|
-
if (!quiet) process.stderr.write(`${error instanceof Error ? error.message : String(error)}
|
|
285
|
-
`);
|
|
286
|
-
exitCode = 1;
|
|
287
|
-
}
|
|
288
|
-
return reportHarnessOutcome(harnessAction, surface, target, exitCode, autoDetected, json, quiet, start);
|
|
289
|
-
}
|
|
290
|
-
if (shellLeafMissing(dispatch.command)) {
|
|
291
|
-
const message = missingShellLeafMessage(dispatch.command);
|
|
292
|
-
if (quiet) {
|
|
293
|
-
return 1;
|
|
294
|
-
} else if (json) {
|
|
295
|
-
console.log(
|
|
296
|
-
harnessSummary(harnessAction, adapter, target, "fail", 1, autoDetected, {
|
|
297
|
-
code: "HARNESS_SPAWN_FAILED",
|
|
298
|
-
message,
|
|
299
|
-
userAction: failureHint(surface, harnessAction)
|
|
300
|
-
})
|
|
301
|
-
);
|
|
302
|
-
} else {
|
|
303
|
-
console.error(`\u2717 ${message}`);
|
|
304
|
-
}
|
|
305
|
-
return 1;
|
|
306
|
-
}
|
|
307
|
-
const result = await spawnScriptStreaming(dispatch.command, [...dispatch.prefixArgs, ...forwardArgs], target, {
|
|
308
|
-
forward: quiet ? "none" : json ? "stderr" : "original",
|
|
309
|
-
stdin: quiet ? "ignore" : "inherit",
|
|
310
|
-
capture: false
|
|
311
|
-
});
|
|
312
|
-
if (result.error) {
|
|
313
|
-
if (quiet) {
|
|
314
|
-
return 1;
|
|
315
|
-
} else if (json) {
|
|
316
|
-
console.log(
|
|
317
|
-
harnessSummary(harnessAction, adapter, target, "fail", 1, autoDetected, {
|
|
318
|
-
code: "HARNESS_SPAWN_FAILED",
|
|
319
|
-
message: `${harnessAction} ${adapter} could not start: ${result.error.message}`,
|
|
320
|
-
userAction: failureHint(surface, harnessAction)
|
|
321
|
-
})
|
|
322
|
-
);
|
|
323
|
-
} else {
|
|
324
|
-
console.error(`\u2717 ${harnessAction} ${adapter} could not start: ${result.error.message}
|
|
325
|
-
${failureHint(surface, harnessAction)}`);
|
|
326
|
-
}
|
|
327
|
-
return 1;
|
|
328
|
-
}
|
|
329
|
-
return reportHarnessOutcome(harnessAction, surface, target, result.status ?? 1, autoDetected, json, quiet, start);
|
|
330
|
-
}
|
|
331
|
-
function reportHarnessOutcome(action, surface, target, exitCode, autoDetected, json, quiet, start) {
|
|
332
|
-
const seconds = ((Date.now() - start) / 1e3).toFixed(1);
|
|
333
|
-
const adapter = surface.id;
|
|
334
|
-
if (quiet) {
|
|
335
|
-
return exitCode;
|
|
336
|
-
} else if (json) {
|
|
337
|
-
console.log(
|
|
338
|
-
harnessSummary(
|
|
339
|
-
action,
|
|
340
|
-
adapter,
|
|
341
|
-
target,
|
|
342
|
-
exitCode === 0 ? "pass" : "fail",
|
|
343
|
-
exitCode,
|
|
344
|
-
autoDetected,
|
|
345
|
-
exitCode === 0 ? void 0 : { code: "HARNESS_FAILED", message: `${action} ${adapter} failed (exit ${exitCode})`, userAction: failureHint(surface, action) }
|
|
346
|
-
)
|
|
347
|
-
);
|
|
348
|
-
} else if (exitCode === 0) {
|
|
349
|
-
console.error(colorHumanMessage(`\u2713 ${action} ${adapter} passed (${seconds}s)
|
|
350
|
-
Next: ${successNext(adapter, action, target)}`));
|
|
351
|
-
} else {
|
|
352
|
-
console.error(colorHumanMessage(`\u2717 ${action} ${adapter} failed (exit ${exitCode}, ${seconds}s)
|
|
353
|
-
${failureHint(surface, action)}`));
|
|
354
|
-
}
|
|
355
|
-
return exitCode;
|
|
356
|
-
}
|
|
357
|
-
async function handleRunwayInstall(adapter, target, forward, json) {
|
|
358
|
-
const { getAdapterSurface } = await import("./adapters/surface.js");
|
|
359
|
-
const rerunCommand = runwayInstallRerunCommand(adapter, target, forward, json);
|
|
360
|
-
const surface = getAdapterSurface(adapter);
|
|
361
|
-
const runtimeDir = argValue(forward, "--runtime-dir");
|
|
362
|
-
const watcherPort = argValue(forward, "--watcher-port");
|
|
363
|
-
const result = await surface.runwayProvision.run(target, {
|
|
364
|
-
json,
|
|
365
|
-
platform: argValue(forward, "--platform") ?? "ios",
|
|
366
|
-
branch: argValue(forward, "--branch"),
|
|
367
|
-
defaultBranch: argValue(forward, "--default-branch"),
|
|
368
|
-
run: argValue(forward, "--run"),
|
|
369
|
-
cacheRoot: argValue(forward, "--cache-root"),
|
|
370
|
-
simulator: argValue(forward, "--simulator") ?? argValue(forward, "--device"),
|
|
371
|
-
runtime: argValue(forward, "--runtime"),
|
|
372
|
-
deviceType: argValue(forward, "--device-type"),
|
|
373
|
-
slot: argValue(forward, "--slot"),
|
|
374
|
-
watcherPort,
|
|
375
|
-
runtimeDir,
|
|
376
|
-
force: hasArg(forward, "--force"),
|
|
377
|
-
resolveOnly: hasArg(forward, "--resolve-only"),
|
|
378
|
-
rerunCommand
|
|
379
|
-
});
|
|
380
|
-
const provisionedSimulator = typeof result.simulator === "object" && result.simulator ? result.simulator : void 0;
|
|
381
|
-
const provisionedDevice = typeof provisionedSimulator?.udid === "string" ? provisionedSimulator.udid : typeof provisionedSimulator?.name === "string" ? provisionedSimulator.name : void 0;
|
|
382
|
-
const next = result.status === "pass" && surface.runwayProvision.launchNext && result.resolveOnly !== true ? `mm-harness launch ${String(result.platform ?? "ios")} --adapter ${adapter} --target ${shellQuote(target)}` + (provisionedDevice ? ` --device ${shellQuote(provisionedDevice)}` : "") : void 0;
|
|
383
|
-
const output = next ? { ...result, next } : result;
|
|
384
|
-
if (json) {
|
|
385
|
-
console.log(JSON.stringify(output, null, 2));
|
|
386
|
-
} else if (result.status === "pass") {
|
|
387
|
-
const cache = typeof result.cache === "object" && result.cache ? result.cache : void 0;
|
|
388
|
-
const simulator = provisionedSimulator;
|
|
389
|
-
const artifact = typeof result.artifact === "object" && result.artifact ? result.artifact : void 0;
|
|
390
|
-
if (result.resolveOnly) {
|
|
391
|
-
console.error(`\u2713 resolved Runway app for ${adapter} ${result.platform ?? ""} run=${artifact?.runId ?? "unknown"} revision=${artifact?.revision ?? "unknown"} artifact=${artifact?.artifactName ?? "unknown"}`);
|
|
392
|
-
} else {
|
|
393
|
-
const action = result.skipped ? "already provisioned" : "installed Runway app";
|
|
394
|
-
console.error(`\u2713 ${action} for ${adapter} ${result.platform ?? ""} simulator=${simulator?.name ?? "unknown"} udid=${simulator?.udid ?? "unknown"} cache=${cache?.status ?? "skip"}`);
|
|
395
|
-
}
|
|
396
|
-
if (next) console.error(` Next: ${next}`);
|
|
397
|
-
} else {
|
|
398
|
-
console.error(`\u2717 mm-harness install --runway: ${result.error?.message ?? "runway install failed"}
|
|
399
|
-
Next: ${result.error?.userAction ?? rerunCommand}`);
|
|
400
|
-
}
|
|
401
|
-
return result.exitCode;
|
|
402
|
-
}
|
|
403
|
-
function runwayInstallRerunCommand(adapter, target, forward, json) {
|
|
404
|
-
const parts = ["mm-harness", "install", "--runway", "--adapter", adapter, "--target", shellQuote(target)];
|
|
405
|
-
const valueFlags = [
|
|
406
|
-
"--platform",
|
|
407
|
-
"--branch",
|
|
408
|
-
"--default-branch",
|
|
409
|
-
"--run",
|
|
410
|
-
"--cache-root",
|
|
411
|
-
"--simulator",
|
|
412
|
-
"--device",
|
|
413
|
-
"--slot",
|
|
414
|
-
"--watcher-port",
|
|
415
|
-
"--runtime-dir",
|
|
416
|
-
"--runtime",
|
|
417
|
-
"--device-type"
|
|
418
|
-
];
|
|
419
|
-
for (const flag of valueFlags) {
|
|
420
|
-
const value = argValue(forward, flag);
|
|
421
|
-
if (value) parts.push(flag, shellQuote(value));
|
|
422
|
-
}
|
|
423
|
-
if (hasArg(forward, "--force")) parts.push("--force");
|
|
424
|
-
if (hasArg(forward, "--resolve-only")) parts.push("--resolve-only");
|
|
425
|
-
if (json) parts.push("--json");
|
|
426
|
-
return parts.join(" ");
|
|
427
|
-
}
|
|
428
|
-
function harnessSummary(action, adapter, target, status, exitCode, autoDetected, error) {
|
|
429
|
-
return JSON.stringify({
|
|
430
|
-
schemaVersion: 1,
|
|
431
|
-
command: "harness",
|
|
432
|
-
action,
|
|
433
|
-
adapter: adapter ?? null,
|
|
434
|
-
target,
|
|
435
|
-
autoDetected,
|
|
436
|
-
status,
|
|
437
|
-
exitCode,
|
|
438
|
-
// Error contract: every --json failure carries a stable machine code + human
|
|
439
|
-
// message. userAction is included when present so callers
|
|
440
|
-
// can surface the reachable escape without parsing the human message.
|
|
441
|
-
...status === "fail" && error ? { error } : {},
|
|
442
|
-
...status === "pass" && adapter ? { next: successNext(adapter, action, target) } : {}
|
|
443
|
-
});
|
|
444
|
-
}
|
|
445
|
-
export {
|
|
446
|
-
ADAPTER_DETECT_NEXT,
|
|
447
|
-
detectAdapter,
|
|
448
|
-
handleHarness,
|
|
449
|
-
readRuntimeContextField,
|
|
450
|
-
resolveRuntimeContextPath
|
|
451
|
-
};
|
package/dist/heal-bounds.js
DELETED
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
|
2
|
-
import fs from "node:fs";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { getAdapterSurface } from "./adapters/surface.js";
|
|
5
|
-
import { handleHarness } from "./harness.js";
|
|
6
|
-
import { recipeHarnessPath, recipeRuntimePath } from "./paths.js";
|
|
7
|
-
import { EXIT } from "./commands/shared.js";
|
|
8
|
-
function newHealState() {
|
|
9
|
-
return { recovered: [], mutations: [], attemptedRecoveries: [] };
|
|
10
|
-
}
|
|
11
|
-
function conciseFailureForHuman(output) {
|
|
12
|
-
const errors = output.split(/\r?\n/u).map((line) => /^(?:[A-Za-z]*Error):\s*(.+)$/u.exec(line.trim())?.[1]).filter((line) => Boolean(line));
|
|
13
|
-
return errors.at(-1) ?? output.trim();
|
|
14
|
-
}
|
|
15
|
-
function parseHeal(options, fallback) {
|
|
16
|
-
const value = options.heal;
|
|
17
|
-
if (value === void 0) return fallback;
|
|
18
|
-
if (value === "off" || value === "infra-only" || value === "auto") return value;
|
|
19
|
-
return { error: `--heal must be off, infra-only, or auto (got "${String(value)}").` };
|
|
20
|
-
}
|
|
21
|
-
function overlayDir(target, adapter) {
|
|
22
|
-
return recipeHarnessPath(target, adapter);
|
|
23
|
-
}
|
|
24
|
-
function overlayPresent(target, adapter) {
|
|
25
|
-
try {
|
|
26
|
-
return fs.statSync(overlayDir(target, adapter)).isDirectory();
|
|
27
|
-
} catch {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
function overlayDelegateValid(target, adapter) {
|
|
32
|
-
if (getAdapterSurface(adapter).headless) return true;
|
|
33
|
-
const pointer = path.join(recipeHarnessPath(target, adapter), "runner", ".runner-source");
|
|
34
|
-
if (!fs.existsSync(pointer)) return true;
|
|
35
|
-
const runnerPath = fs.readFileSync(pointer, "utf8").trim();
|
|
36
|
-
if (!Boolean(runnerPath) || !fs.existsSync(runnerPath)) return false;
|
|
37
|
-
return fs.existsSync(path.join(runnerPath, "bin", "mm-harness"));
|
|
38
|
-
}
|
|
39
|
-
async function ensureOverlay(adapter, target, heal, state, json) {
|
|
40
|
-
if (getAdapterSurface(adapter).headless) return { ok: true };
|
|
41
|
-
if (overlayPresent(target, adapter) && overlayDelegateValid(target, adapter)) return { ok: true };
|
|
42
|
-
if (heal === "off") return { ok: true };
|
|
43
|
-
const installBin = process.env.MM_HARNESS_INSTALL_BIN;
|
|
44
|
-
let code;
|
|
45
|
-
if (installBin) {
|
|
46
|
-
const result = spawnSync(installBin, ["install", "--platform", adapter, "--target", target], {
|
|
47
|
-
cwd: target,
|
|
48
|
-
stdio: ["ignore", 2, "inherit"],
|
|
49
|
-
env: process.env
|
|
50
|
-
});
|
|
51
|
-
code = result.status ?? 1;
|
|
52
|
-
} else {
|
|
53
|
-
code = await handleHarness(["install", "--platform", adapter, "--target", target, "--quiet"]);
|
|
54
|
-
}
|
|
55
|
-
if (code !== 0 || !overlayPresent(target, adapter)) {
|
|
56
|
-
return { ok: false, error: `runtime overlay install failed (exit ${code})` };
|
|
57
|
-
}
|
|
58
|
-
const dir = overlayDir(target, adapter);
|
|
59
|
-
state.mutations.push({ type: "file", action: "created", path: dir });
|
|
60
|
-
if (!json) process.stderr.write(`installed mm-harness overlay \u2192 ${dir}
|
|
61
|
-
`);
|
|
62
|
-
return { ok: true };
|
|
63
|
-
}
|
|
64
|
-
function classifyFailure(output) {
|
|
65
|
-
if (/SCREENSHOT_PROTECTED|screenshot is protected by FLAG_SECURE/iu.test(output)) return "screenshot-protected";
|
|
66
|
-
if (/CDP_TIMEOUT|Mobile CDP bridge command timed out|NO_TARGET|WS_CLOSED/iu.test(output)) return "infra";
|
|
67
|
-
if (/fixture|keyring|not seeded|\bsrp\b|password|onboard/iu.test(output)) return "wallet";
|
|
68
|
-
if (/metro|cdp|chrome|bridge|bundle|packager|port\b|econnrefused|not reachable|watcher|dev client|websocket/iu.test(output)) {
|
|
69
|
-
return "infra";
|
|
70
|
-
}
|
|
71
|
-
return "app";
|
|
72
|
-
}
|
|
73
|
-
function recipeRunning(target) {
|
|
74
|
-
if (process.env.MM_HARNESS_RECIPE_RUNNING === "1") return true;
|
|
75
|
-
return fs.existsSync(recipeRuntimePath(target, "recipe.lock"));
|
|
76
|
-
}
|
|
77
|
-
const RECOVERY_CODE = {
|
|
78
|
-
mobile: "metro.restarted",
|
|
79
|
-
extension: "chrome.reopened"
|
|
80
|
-
};
|
|
81
|
-
function checkHealBounds(target, output, state) {
|
|
82
|
-
const originalError = output.trim() || void 0;
|
|
83
|
-
if (recipeRunning(target)) {
|
|
84
|
-
return {
|
|
85
|
-
code: "RECIPE_RUNNING",
|
|
86
|
-
exitCode: EXIT.bounded,
|
|
87
|
-
message: "a recipe is currently running \u2014 refusing recovery to avoid corrupting mid-run state.",
|
|
88
|
-
originalError
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
const failureClass = classifyFailure(conciseFailureForHuman(output));
|
|
92
|
-
if (failureClass === "screenshot-protected") {
|
|
93
|
-
return {
|
|
94
|
-
code: "SCREENSHOT_PROTECTED",
|
|
95
|
-
exitCode: EXIT.runtime,
|
|
96
|
-
message: "the focused Android window intentionally blocks screenshots; a black capture cannot be used as evidence.",
|
|
97
|
-
userAction: "unlock or navigate to a non-protected screen, then rerun the screenshot action",
|
|
98
|
-
originalError
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
if (failureClass === "wallet") {
|
|
102
|
-
return {
|
|
103
|
-
code: "WALLET_STATE_REQUIRED",
|
|
104
|
-
exitCode: EXIT.bounded,
|
|
105
|
-
message: "wallet prerequisites need attention; healing never changes wallet state.",
|
|
106
|
-
userAction: /(?:^|\n)\s*Next:\s*([^\r\n]+)/u.exec(output)?.[1] ?? "run mm-harness doctor --json",
|
|
107
|
-
originalError
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
if (failureClass === "app") {
|
|
111
|
-
return {
|
|
112
|
-
code: "APP_LOGIC_FAILURE",
|
|
113
|
-
exitCode: EXIT.runtime,
|
|
114
|
-
message: "failure looks like app-logic \u2014 healing cannot help; surface verbatim.",
|
|
115
|
-
originalError
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
if (state.attemptedRecoveries.length > 0) {
|
|
119
|
-
return {
|
|
120
|
-
code: "SAME_RECOVERY_TWICE",
|
|
121
|
-
exitCode: EXIT.bounded,
|
|
122
|
-
message: state.recovered.length > 0 ? "one recovery already succeeded this invocation \u2014 bounded policy refuses a second recovery." : "one recovery was already attempted this invocation \u2014 refusing to loop.",
|
|
123
|
-
originalError
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
export {
|
|
129
|
-
RECOVERY_CODE,
|
|
130
|
-
checkHealBounds,
|
|
131
|
-
classifyFailure,
|
|
132
|
-
conciseFailureForHuman,
|
|
133
|
-
ensureOverlay,
|
|
134
|
-
newHealState,
|
|
135
|
-
parseHeal,
|
|
136
|
-
recipeRunning
|
|
137
|
-
};
|
package/dist/json-stream.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { recordCommandStage } from "./command-journal.js";
|
|
2
|
-
class JsonStreamWriter {
|
|
3
|
-
enabled;
|
|
4
|
-
command;
|
|
5
|
-
completed = false;
|
|
6
|
-
writeLine;
|
|
7
|
-
constructor(command, enabled, output = process.stdout) {
|
|
8
|
-
this.command = command;
|
|
9
|
-
this.enabled = enabled;
|
|
10
|
-
const write = output.write.bind(output);
|
|
11
|
-
this.writeLine = (line) => {
|
|
12
|
-
write(`${line}
|
|
13
|
-
`);
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
isolateStdout() {
|
|
17
|
-
if (!this.enabled) return () => void 0;
|
|
18
|
-
const original = process.stdout.write;
|
|
19
|
-
const redirect = ((chunk, encoding, callback) => process.stderr.write(chunk, encoding, callback));
|
|
20
|
-
process.stdout.write = redirect;
|
|
21
|
-
return () => {
|
|
22
|
-
if (process.stdout.write === redirect) process.stdout.write = original;
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
emit(event, fields = {}) {
|
|
26
|
-
if (!this.enabled || this.completed) return;
|
|
27
|
-
this.writeLine(JSON.stringify({
|
|
28
|
-
schemaVersion: 1,
|
|
29
|
-
command: this.command,
|
|
30
|
-
event,
|
|
31
|
-
...fields,
|
|
32
|
-
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
33
|
-
}));
|
|
34
|
-
}
|
|
35
|
-
phase(phase, fields = {}) {
|
|
36
|
-
recordCommandStage(phase);
|
|
37
|
-
this.emit("phase", { phase, ...fields });
|
|
38
|
-
}
|
|
39
|
-
node(nodeId, action, status) {
|
|
40
|
-
if (status === "running") recordCommandStage(`${nodeId}: ${action}`);
|
|
41
|
-
this.emit("node", { nodeId, action, status });
|
|
42
|
-
}
|
|
43
|
-
mutation(mutation) {
|
|
44
|
-
this.emit("mutation", { mutation });
|
|
45
|
-
}
|
|
46
|
-
recovery(code) {
|
|
47
|
-
this.emit("recovery", { code });
|
|
48
|
-
}
|
|
49
|
-
error(error) {
|
|
50
|
-
this.emit("error", { error });
|
|
51
|
-
}
|
|
52
|
-
complete(status, exitCode, fields = {}) {
|
|
53
|
-
if (!this.enabled || this.completed) return;
|
|
54
|
-
this.emit("complete", { status, exitCode, ...fields });
|
|
55
|
-
this.completed = true;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
export {
|
|
59
|
-
JsonStreamWriter
|
|
60
|
-
};
|
package/dist/leaf-invoke.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
function resolveLeafInvoke(command, args) {
|
|
4
|
-
if (command.endsWith(".sh")) return { bin: "bash", args: [command, ...args] };
|
|
5
|
-
return { bin: command, args };
|
|
6
|
-
}
|
|
7
|
-
function missingShellLeafMessage(leafPath) {
|
|
8
|
-
const leaf = path.basename(leafPath);
|
|
9
|
-
return `leaf could not start: ${leaf} (ENOENT)
|
|
10
|
-
Next: reinstall mm-harness (npm i -g @deeeed/metamask-harness) \u2014 the shell leaf is missing or not executable`;
|
|
11
|
-
}
|
|
12
|
-
function shellLeafMissing(leafPath) {
|
|
13
|
-
return leafPath.endsWith(".sh") && !fs.existsSync(leafPath);
|
|
14
|
-
}
|
|
15
|
-
export {
|
|
16
|
-
missingShellLeafMessage,
|
|
17
|
-
resolveLeafInvoke,
|
|
18
|
-
shellLeafMissing
|
|
19
|
-
};
|