@deeeed/metamask-harness 0.74.0 → 0.75.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 +17 -1
- package/README.md +1 -1
- package/adapters/shared/ensure-runner-deps.sh +15 -3
- package/dist/action-values.js +15 -0
- package/dist/adapters/core/actions.js +20 -0
- package/dist/adapters/core/live-script-env.js +36 -0
- package/dist/adapters/core/run.js +54 -0
- package/dist/adapters/core/surface.js +5 -1
- package/dist/adapters/extension/action-inputs.js +206 -0
- package/dist/adapters/extension/actions.js +51 -0
- package/dist/adapters/extension/console-capture.js +13 -1
- package/dist/adapters/extension/launch.js +315 -0
- package/dist/adapters/extension/launched-browser.js +51 -0
- package/dist/adapters/extension/run.js +105 -0
- package/dist/adapters/extension/surface.js +9 -2
- package/dist/adapters/mobile/actions.js +54 -0
- package/dist/adapters/mobile/launch.js +192 -0
- package/dist/adapters/mobile/lifecycle.js +300 -0
- package/dist/adapters/mobile/run.js +156 -0
- package/dist/adapters/mobile/runtime-identity.js +34 -0
- package/dist/adapters/mobile/surface.js +11 -2
- package/dist/adapters/mobile/ui.js +701 -0
- package/dist/adapters/performance/cdp-trace.js +24 -6
- package/dist/adapters/performance/device-platform.js +10 -0
- package/dist/adapters/registry.js +1 -1
- package/dist/adapters/terminal/actions.js +43 -0
- package/dist/adapters/terminal/console-capture.js +14 -1
- package/dist/adapters/terminal/run.js +30 -0
- package/dist/adapters/terminal/surface.js +6 -1
- package/dist/adapters.js +32 -824
- package/dist/cli-commands.js +1 -0
- package/dist/command-contract.js +3 -0
- package/dist/commands/call.js +2 -5
- package/dist/commands/launch/device.js +2 -6
- package/dist/commands/launch/extension.js +3 -303
- package/dist/commands/launch/index.js +1 -1
- package/dist/commands/launch/mobile.js +2 -190
- package/dist/commands/launch/quote.js +7 -0
- package/dist/commands/pin.js +226 -0
- package/dist/commands/run-engine.js +38 -138
- package/dist/commands/run-report.js +4 -48
- package/dist/commands/run.js +6 -48
- package/dist/doctor.js +3 -1
- package/dist/execution-provenance.js +3 -2
- package/dist/harness-pin.js +10 -0
- package/dist/heal-bounds.js +3 -2
- package/dist/live-adapter-contract.js +8 -34
- package/dist/manifest.js +3 -5
- package/dist/metamask-action-validation.js +5 -196
- package/dist/mm-harness-cli.js +27 -2
- package/dist/network-observation.js +10 -3
- package/dist/performance-observation.js +15 -22
- package/dist/pr-body/render.js +3 -1
- package/dist/recording-target.js +4 -39
- package/dist/run-diagnostics.js +21 -60
- package/dist/run-recording.js +5 -4
- package/dist/runner.js +20 -368
- package/docs/CONTRIBUTING.md +19 -7
- package/package.json +2 -1
- package/scripts/completions.sh +2 -1
|
@@ -18,6 +18,22 @@ const EXTENSION_TRACE_CATEGORIES = [
|
|
|
18
18
|
"disabled-by-default-devtools.timeline.frame",
|
|
19
19
|
"v8.execute"
|
|
20
20
|
];
|
|
21
|
+
const MOBILE_TRACE_KIND = {
|
|
22
|
+
categories: MOBILE_TRACE_CATEGORIES,
|
|
23
|
+
rendererScoped: false,
|
|
24
|
+
nativeSource: "react-native-cdp-frame-timings",
|
|
25
|
+
javascriptTasks: false
|
|
26
|
+
};
|
|
27
|
+
const TRACE_KINDS = {
|
|
28
|
+
extension: {
|
|
29
|
+
categories: EXTENSION_TRACE_CATEGORIES,
|
|
30
|
+
rendererScoped: true,
|
|
31
|
+
nativeSource: "chromium-cdp-frame-timings",
|
|
32
|
+
javascriptTasks: true
|
|
33
|
+
},
|
|
34
|
+
ios: MOBILE_TRACE_KIND,
|
|
35
|
+
android: MOBILE_TRACE_KIND
|
|
36
|
+
};
|
|
21
37
|
function createCdpTraceCollector(client, platform, marker) {
|
|
22
38
|
let active;
|
|
23
39
|
const offData = client.on("Tracing.dataCollected", (params) => {
|
|
@@ -60,7 +76,7 @@ function createCdpTraceCollector(client, platform, marker) {
|
|
|
60
76
|
await client.send(
|
|
61
77
|
"Tracing.start",
|
|
62
78
|
{
|
|
63
|
-
categories:
|
|
79
|
+
categories: TRACE_KINDS[platform].categories.join(","),
|
|
64
80
|
transferMode: "ReportEvents"
|
|
65
81
|
},
|
|
66
82
|
15e3
|
|
@@ -126,7 +142,8 @@ function createCdpTraceCollector(client, platform, marker) {
|
|
|
126
142
|
}
|
|
127
143
|
function parseTraceCapture(capture) {
|
|
128
144
|
const marker = findClockMarker(capture.events, capture.markerName);
|
|
129
|
-
|
|
145
|
+
const kind = TRACE_KINDS[capture.platform];
|
|
146
|
+
if (kind.rendererScoped && !finite(marker?.pid)) {
|
|
130
147
|
const reason = "Extension trace marker did not identify a renderer process.";
|
|
131
148
|
return {
|
|
132
149
|
platform: capture.platform,
|
|
@@ -135,12 +152,12 @@ function parseTraceCapture(capture) {
|
|
|
135
152
|
trace: traceEvidence(capture, "unresolved")
|
|
136
153
|
};
|
|
137
154
|
}
|
|
138
|
-
const scopedEvents =
|
|
139
|
-
const scope =
|
|
155
|
+
const scopedEvents = kind.rendererScoped && finite(marker?.pid) ? capture.events.filter((event) => event.pid === marker.pid) : capture.events;
|
|
156
|
+
const scope = !kind.rendererScoped ? "mobile-host" : finite(marker?.pid) ? "extension-renderer" : "unresolved";
|
|
140
157
|
const trace = traceEvidence(
|
|
141
158
|
{ ...capture, events: scopedEvents },
|
|
142
159
|
scope,
|
|
143
|
-
|
|
160
|
+
kind.rendererScoped && finite(marker?.pid) ? marker.pid : void 0
|
|
144
161
|
);
|
|
145
162
|
if (!finite(marker?.ts) || capture.markerHostEpochMs === void 0 || capture.markerUncertaintyMs === void 0) {
|
|
146
163
|
const reason = "CDP trace clock marker was unavailable.";
|
|
@@ -181,7 +198,7 @@ function parseTraceCapture(capture) {
|
|
|
181
198
|
capture.markerUncertaintyMs
|
|
182
199
|
),
|
|
183
200
|
nativeUi: nativeUiSourceResult(
|
|
184
|
-
|
|
201
|
+
kind.nativeSource,
|
|
185
202
|
nativeSamples,
|
|
186
203
|
status,
|
|
187
204
|
gapReasons,
|
|
@@ -383,6 +400,7 @@ function asRecord(value) {
|
|
|
383
400
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
384
401
|
}
|
|
385
402
|
export {
|
|
403
|
+
TRACE_KINDS,
|
|
386
404
|
createCdpTraceCollector,
|
|
387
405
|
parseTraceCapture
|
|
388
406
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
function devicePlatformFromEnv(env) {
|
|
2
|
+
const explicit = String(
|
|
3
|
+
env.MM_HARNESS_EXPLICIT_PLATFORM ?? env.RECIPE_HARNESS_PLATFORM ?? ""
|
|
4
|
+
).toLowerCase();
|
|
5
|
+
if (explicit === "android" || explicit === "ios") return explicit;
|
|
6
|
+
return env.ADB_SERIAL || env.ANDROID_SERIAL || env.ANDROID_DEVICE ? "android" : "ios";
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
devicePlatformFromEnv
|
|
10
|
+
};
|
|
@@ -6,7 +6,7 @@ const adapterRegistry = {
|
|
|
6
6
|
},
|
|
7
7
|
get(id) {
|
|
8
8
|
const surface = surfaces.get(id);
|
|
9
|
-
if (!surface) throw new Error(`unknown adapter '${id}' (registered: ${
|
|
9
|
+
if (!surface) throw new Error(`unknown adapter '${id}' (registered: ${adapterRegistry.list().join(", ")})`);
|
|
10
10
|
return surface;
|
|
11
11
|
},
|
|
12
12
|
has: (id) => surfaces.has(id),
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { manifestPath } from "../../paths.js";
|
|
2
|
+
const terminalActions = {
|
|
3
|
+
manifestPath: () => manifestPath("terminal"),
|
|
4
|
+
semantic: [
|
|
5
|
+
"app.network_capture",
|
|
6
|
+
"app.network_assert",
|
|
7
|
+
"app.performance_capture",
|
|
8
|
+
"app.performance_assert"
|
|
9
|
+
],
|
|
10
|
+
cdpTarget: { transport: "chrome-cdp", probePath: "json/version" },
|
|
11
|
+
ui: (harness, { hudPolicy }) => ({
|
|
12
|
+
base: harness.createCdpWebUiTransport({
|
|
13
|
+
async withPage(input, callback) {
|
|
14
|
+
const { withTerminalPage } = await import("../../../library/actions/terminal/platform/page.mjs");
|
|
15
|
+
return withTerminalPage(
|
|
16
|
+
{
|
|
17
|
+
action: input.action,
|
|
18
|
+
node: input.node,
|
|
19
|
+
context: {
|
|
20
|
+
nodeId: input.context.nodeId,
|
|
21
|
+
projectRoot: input.context.projectRoot,
|
|
22
|
+
artifactsDir: input.context.artifactsDir
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
callback
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
}),
|
|
29
|
+
async execute(action, node, context, standard) {
|
|
30
|
+
if (action === "app.hud") {
|
|
31
|
+
const { showTerminalHud } = await import("../../../library/actions/terminal/platform/hud.mjs");
|
|
32
|
+
return showTerminalHud(
|
|
33
|
+
{ action, node, context: { nodeId: context.nodeId, projectRoot: context.projectRoot } },
|
|
34
|
+
{ hudPolicy }
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return standard();
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
};
|
|
41
|
+
export {
|
|
42
|
+
terminalActions
|
|
43
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { verifyCapture } from "../../../library/actions/shared/console-collector.mjs";
|
|
3
4
|
import { recipeRuntimePath } from "../../paths.js";
|
|
4
5
|
import { ensureConsoleCollector } from "../console-capture.js";
|
|
5
6
|
const TERMINAL_CONSOLE_FILES = Object.freeze({
|
|
@@ -37,10 +38,22 @@ async function ensureTerminalConsoleCapture(target) {
|
|
|
37
38
|
cwd: target
|
|
38
39
|
});
|
|
39
40
|
}
|
|
41
|
+
async function verifyTerminalConsoleControl(capture) {
|
|
42
|
+
let browser = null;
|
|
43
|
+
try {
|
|
44
|
+
const value = JSON.parse(fs.readFileSync(terminalRuntimeFile(capture.projectRoot, "browser.json"), "utf8"));
|
|
45
|
+
browser = typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
46
|
+
} catch {
|
|
47
|
+
browser = null;
|
|
48
|
+
}
|
|
49
|
+
if (typeof browser?.appOrigin !== "string") return { ok: false, detail: "no slot browser state (browser.json) to verify the page console capture against" };
|
|
50
|
+
return verifyCapture({ cdpPort: capture.cdpPort, log: capture.pageLog, target: "page", appOrigin: browser.appOrigin });
|
|
51
|
+
}
|
|
40
52
|
export {
|
|
41
53
|
TERMINAL_CONSOLE_FILES,
|
|
42
54
|
ensureTerminalConsoleCapture,
|
|
43
55
|
terminalCaptureFiles,
|
|
44
56
|
terminalCdpPort,
|
|
45
|
-
terminalRuntimeFile
|
|
57
|
+
terminalRuntimeFile,
|
|
58
|
+
verifyTerminalConsoleControl
|
|
46
59
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { devicePlatformFromEnv } from "../performance/device-platform.js";
|
|
2
|
+
import {
|
|
3
|
+
ensureTerminalConsoleCapture,
|
|
4
|
+
terminalCaptureFiles,
|
|
5
|
+
terminalCdpPort,
|
|
6
|
+
terminalRuntimeFile,
|
|
7
|
+
verifyTerminalConsoleControl
|
|
8
|
+
} from "./console-capture.js";
|
|
9
|
+
const terminalDiagnostics = {
|
|
10
|
+
console: {
|
|
11
|
+
start: (projectRoot) => ensureTerminalConsoleCapture(projectRoot),
|
|
12
|
+
files: (projectRoot) => terminalCaptureFiles(projectRoot),
|
|
13
|
+
cdpPort: () => terminalCdpPort(),
|
|
14
|
+
verifyControl: (capture) => verifyTerminalConsoleControl(capture)
|
|
15
|
+
},
|
|
16
|
+
walletLog: (projectRoot) => terminalRuntimeFile(projectRoot, "wallet-requests.jsonl")
|
|
17
|
+
};
|
|
18
|
+
const terminalObservation = {
|
|
19
|
+
network: {
|
|
20
|
+
backend: async (_target, env, artifactsDir) => (await import("../../network-observation.js")).createExtensionNetworkBackend(env, artifactsDir)
|
|
21
|
+
},
|
|
22
|
+
performance: {
|
|
23
|
+
backend: async (target, env, ports) => (await import("../../performance-observation.js")).createExtensionPerformanceObserver(target, env, ports),
|
|
24
|
+
platform: (env) => devicePlatformFromEnv(env)
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
export {
|
|
28
|
+
terminalDiagnostics,
|
|
29
|
+
terminalObservation
|
|
30
|
+
};
|
|
@@ -4,6 +4,8 @@ import fs from "node:fs";
|
|
|
4
4
|
import { TERMINAL_CONSOLE_FILES, terminalRuntimeFile } from "./console-capture.js";
|
|
5
5
|
import { stopTerminalBrowserSync } from "./stop.js";
|
|
6
6
|
import { adapterRegistry } from "../registry.js";
|
|
7
|
+
import { terminalActions } from "./actions.js";
|
|
8
|
+
import { terminalDiagnostics, terminalObservation } from "./run.js";
|
|
7
9
|
function portFromEnv(...names) {
|
|
8
10
|
for (const name of names) {
|
|
9
11
|
const raw = process.env[name];
|
|
@@ -97,7 +99,10 @@ const terminalSurface = {
|
|
|
97
99
|
relaunch: "mm-harness launch --adapter terminal --fresh-profile",
|
|
98
100
|
runtimeProbeRecovery: (target) => `mm-harness doctor --adapter terminal --target ${shellQuote(path.resolve(target))}`
|
|
99
101
|
},
|
|
100
|
-
launch: async (context) => (await import("./launch.js")).launchTerminal(context)
|
|
102
|
+
launch: async (context) => (await import("./launch.js")).launchTerminal(context),
|
|
103
|
+
actions: terminalActions,
|
|
104
|
+
diagnostics: terminalDiagnostics,
|
|
105
|
+
observation: terminalObservation
|
|
101
106
|
};
|
|
102
107
|
adapterRegistry.register(terminalSurface);
|
|
103
108
|
export {
|