@deeeed/metamask-harness 0.2.0 → 0.3.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 -0
- package/README.md +20 -17
- package/{orchestration → adapters}/core/cleanup.sh +2 -2
- package/{orchestration → adapters}/core/inject.sh +8 -8
- package/{orchestration → adapters}/extension/cleanup.mjs +1 -1
- package/{orchestration → adapters}/extension/console-tail.mjs +3 -0
- package/{orchestration → adapters}/extension/ensure-browser.sh +4 -4
- package/{orchestration → adapters}/extension/inject.mjs +27 -31
- package/{orchestration → adapters}/extension/launch.sh +4 -4
- package/{orchestration → adapters}/extension/live.sh +5 -5
- package/{orchestration → adapters}/extension/readiness.mjs +12 -2
- package/{orchestration → adapters}/extension/refresh-build.sh +1 -1
- package/{orchestration → adapters}/extension/seed-fixture.sh +1 -1
- package/{orchestration → adapters}/extension/start-watch.sh +7 -7
- package/{runner → adapters}/extension/verify.sh +11 -11
- package/{orchestration → adapters}/extension/wallet-fixture-state.cjs +2 -2
- package/{orchestration → adapters}/manifest.json +96 -96
- package/{library/actions → adapters}/mobile/bridge-runtime/cdp-bridge.cjs +5 -5
- package/{orchestration → adapters}/mobile/cleanup.sh +3 -3
- package/{orchestration → adapters}/mobile/inject.sh +22 -24
- package/adapters/mobile/open-device.sh +250 -0
- package/{orchestration/compat-overlays → adapters/mobile/overlay/compat}/README.md +13 -4
- package/adapters/mobile/prewarm-bundle.sh +95 -0
- package/adapters/mobile/start-metro.sh +228 -0
- package/{runner → adapters}/mobile/verify.sh +6 -6
- package/adapters/mobile/wait-for-bridge.sh +108 -0
- package/adapters/mobile/yarn-setup.sh +20 -0
- package/{orchestration/lib → adapters/shared}/cli-ux.sh +5 -9
- package/{orchestration/lib → adapters/shared}/log-tui.mjs +57 -1
- package/{orchestration/lib → adapters/shared}/open-debug.mjs +32 -10
- package/{orchestration/lib → adapters/shared}/resolve-farmslot-ports.sh +47 -0
- package/adapters/shared/sync-wallet-fixture.sh +78 -0
- package/bin/mm-harness +5 -6
- package/docs/CLI-SPEC.md +41 -2
- package/docs/architecture.md +69 -38
- package/docs/runtime-file-conventions.md +3 -3
- package/library/actions/core/perps/_controller.mjs +1 -1
- package/library/actions/extension/platform/cdp.mjs +2 -2
- package/library/actions/extension/wallet/ensure_unlocked.mjs +1 -1
- package/library/actions/mobile/platform/bridge.mjs +1 -1
- package/library/actions/mobile/wallet/ensure_unlocked.mjs +1 -1
- package/library/actions/mobile/wallet/setup.mjs +2 -2
- package/library/library.json +1 -1
- package/package.json +8 -8
- package/{orchestration → src/adapters}/extension/runtime-decision.ts +5 -5
- package/{orchestration → src/adapters}/extension/runtime.ts +1 -1
- package/src/adapters/mobile/prepare.ts +210 -0
- package/{orchestration → src/adapters}/mobile/runtime-decision.ts +11 -3
- package/{runner/src → src}/adapters.ts +3 -3
- package/{orchestration/lib/cli-color.mjs → src/cli-color.ts} +21 -13
- package/{orchestration/lib/cli-commands.mjs → src/cli-commands.ts} +52 -45
- package/{orchestration/lib/cli-version.mjs → src/cli-version.ts} +35 -17
- package/{runner/src → src}/cli.ts +25 -18
- package/src/commands/debug.ts +61 -0
- package/src/commands/fixtures.ts +196 -0
- package/{runner/src → src}/commands/launch.ts +185 -41
- package/src/commands/logs.ts +86 -0
- package/{runner/src → src}/commands/shared.ts +26 -26
- package/{runner/src → src}/harness.ts +97 -10
- package/src/index.ts +15 -0
- package/{runner/src → src}/live-adapter-contract.ts +1 -1
- package/{runner/src → src}/mm-harness-cli.ts +19 -3
- package/{runner/src → src}/paths.ts +2 -2
- package/{orchestration/lib/progress.mjs → src/progress.ts} +31 -21
- package/docs/extension-runtime-commands.md +0 -60
- package/docs/harness-cli.md +0 -43
- package/orchestration/compat-overlays/mobile/README.md +0 -13
- package/orchestration/doctor.mjs +0 -72
- package/orchestration/lib/cli-home.mjs +0 -354
- package/orchestration/lib/recipe-paths.mjs +0 -26
- package/orchestration/mobile/launch.sh +0 -137
- package/orchestration/mobile/live.sh +0 -125
- package/orchestration/porcelain/metamask-recipe +0 -99
- package/orchestration/porcelain/mm-recipe +0 -1591
- package/orchestration/porcelain/mme-recipe +0 -1181
- package/runner/src/commands/debug.ts +0 -44
- package/runner/src/commands/fixtures.ts +0 -99
- package/runner/src/commands/logs.ts +0 -60
- package/runner/src/index.ts +0 -6
- /package/{orchestration → adapters}/extension/launch-browser.cjs +0 -0
- /package/{orchestration → adapters}/extension/pin-remote-flags.cjs +0 -0
- /package/{orchestration → adapters}/extension/sidepanel-toggle.sh +0 -0
- /package/{orchestration → adapters}/extension/snapshot-dist.sh +0 -0
- /package/{library/actions → adapters}/mobile/bridge-runtime/lib/cdp-eval.cjs +0 -0
- /package/{library/actions → adapters}/mobile/bridge-runtime/lib/config.cjs +0 -0
- /package/{library/actions → adapters}/mobile/bridge-runtime/lib/issue-capture.cjs +0 -0
- /package/{library/actions → adapters}/mobile/bridge-runtime/lib/target-discovery.cjs +0 -0
- /package/{library/actions → adapters}/mobile/bridge-runtime/lib/ws-client.cjs +0 -0
- /package/{library/actions → adapters}/mobile/bridge-runtime/setup-wallet.sh +0 -0
- /package/{library/actions/mobile/app-overlay → adapters/mobile/overlay}/app/dev-tools/AgenticService/AgentStepHud.tsx.patch +0 -0
- /package/{library/actions/mobile/app-overlay → adapters/mobile/overlay}/app/dev-tools/AgenticService/AgenticService.ts.patch +0 -0
- /package/{orchestration/compat-overlays/mobile → adapters/mobile/overlay/compat}/rn81-message-event-source.patch +0 -0
- /package/{orchestration/lib → adapters/shared}/activate-repo-node.sh +0 -0
- /package/{orchestration/lib → adapters/shared}/ensure-runner-deps.sh +0 -0
- /package/{orchestration/lib → adapters/shared}/harness-path.sh +0 -0
- /package/{orchestration/lib → adapters/shared}/hash-helpers.sh +0 -0
- /package/{orchestration/lib → adapters/shared}/json-field.sh +0 -0
- /package/{orchestration/lib → adapters/shared}/path-defaults.json +0 -0
- /package/{orchestration → src/adapters}/extension/ensure-ready.ts +0 -0
- /package/{orchestration → src/adapters}/extension/extension-id.ts +0 -0
- /package/{orchestration → src/adapters}/mobile/deps-markers.ts +0 -0
- /package/{runner/src → src}/completions-cache.ts +0 -0
- /package/{runner/src → src}/doctor.ts +0 -0
- /package/{runner/src → src}/heal-bounds.ts +0 -0
- /package/{runner/src → src}/manifest.ts +0 -0
- /package/{runner/src → src}/recording-target.ts +0 -0
- /package/{runner/src → src}/run-recording.ts +0 -0
- /package/{runner/src → src}/runner.ts +0 -0
- /package/{runner/src → src}/types.ts +0 -0
|
@@ -2,8 +2,8 @@ import http from 'node:http';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { compatibilityMode, fixtureSummary, repoShape } from './doctor.ts';
|
|
4
4
|
import { runLiveAdapterScript } from './live-adapter-contract.ts';
|
|
5
|
-
import { withExtensionPage } from '
|
|
6
|
-
import { bridgeCommand, evalSync, simulatorScreenshot } from '
|
|
5
|
+
import { withExtensionPage } from '../library/actions/extension/platform/cdp.mjs';
|
|
6
|
+
import { bridgeCommand, evalSync, simulatorScreenshot } from '../library/actions/mobile/platform/bridge.mjs';
|
|
7
7
|
import type {
|
|
8
8
|
ActionAdapter,
|
|
9
9
|
ActionExecutionContext,
|
|
@@ -284,7 +284,7 @@ function mobileProbeOutput(status: unknown, input: MetaMaskUiActionInput, projec
|
|
|
284
284
|
}
|
|
285
285
|
|
|
286
286
|
function mobileBridgePath(_projectRoot: string): string {
|
|
287
|
-
return process.env.METAMASK_RECIPE_MOBILE_BRIDGE_SCRIPT || 'runner:
|
|
287
|
+
return process.env.METAMASK_RECIPE_MOBILE_BRIDGE_SCRIPT || 'runner:adapters/mobile/bridge-runtime/cdp-bridge.cjs';
|
|
288
288
|
}
|
|
289
289
|
|
|
290
290
|
async function waitForMobileTarget(input: ReturnType<typeof uiInputFor>, payload: ActionNode) {
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
/**
|
|
3
|
-
* cli-color.
|
|
2
|
+
* cli-color.ts — shared ANSI styling for recipe CLI human output.
|
|
4
3
|
*
|
|
5
4
|
* Honors NO_COLOR, RECIPE_NO_COLOR, FORCE_COLOR, RECIPE_COLOR, and TTY detection.
|
|
6
5
|
*/
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
type StyleName =
|
|
8
|
+
| 'reset' | 'bold' | 'dim' | 'label' | 'cmd' | 'ok' | 'warn'
|
|
9
|
+
| 'err' | 'info' | 'accent' | 'path' | 'comment' | 'active';
|
|
10
|
+
|
|
11
|
+
const STYLES: Record<StyleName, string> = {
|
|
9
12
|
reset: '\x1b[0m',
|
|
10
13
|
bold: '\x1b[1m',
|
|
11
14
|
dim: '\x1b[2m',
|
|
@@ -21,32 +24,37 @@ const STYLES = {
|
|
|
21
24
|
active: '\x1b[1m',
|
|
22
25
|
};
|
|
23
26
|
|
|
24
|
-
export function colorEnabled(stream = process.stderr) {
|
|
27
|
+
export function colorEnabled(stream: NodeJS.WriteStream = process.stderr): boolean {
|
|
25
28
|
if (process.env.NO_COLOR != null && process.env.NO_COLOR !== '' && process.env.NO_COLOR !== '0') {
|
|
26
29
|
return false;
|
|
27
30
|
}
|
|
28
31
|
if (process.env.RECIPE_NO_COLOR === '1') return false;
|
|
29
32
|
if (process.env.RECIPE_COLOR === '1' || process.env.FORCE_COLOR === '1') return true;
|
|
30
|
-
return Boolean(stream?.isTTY);
|
|
33
|
+
return Boolean((stream as NodeJS.WriteStream & { isTTY?: boolean })?.isTTY);
|
|
31
34
|
}
|
|
32
35
|
|
|
33
|
-
export function stripAnsi(text) {
|
|
36
|
+
export function stripAnsi(text: string): string {
|
|
34
37
|
return String(text).replace(/\x1b\[[0-9;]*m/gu, '');
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
export function color(style, text, { stream = process.stderr } = {}) {
|
|
40
|
+
export function color(style: string, text: string, { stream = process.stderr }: { stream?: NodeJS.WriteStream } = {}): string {
|
|
38
41
|
const value = String(text);
|
|
39
42
|
if (!colorEnabled(stream)) return value;
|
|
40
|
-
const code = STYLES[style];
|
|
43
|
+
const code = STYLES[style as StyleName];
|
|
41
44
|
if (!code) return value;
|
|
42
45
|
return `${code}${value}${STYLES.reset}`;
|
|
43
46
|
}
|
|
44
47
|
|
|
45
|
-
export function colorKv(
|
|
48
|
+
export function colorKv(
|
|
49
|
+
label: string,
|
|
50
|
+
value: string,
|
|
51
|
+
valueStyle = 'info',
|
|
52
|
+
{ stream = process.stderr }: { stream?: NodeJS.WriteStream } = {},
|
|
53
|
+
): string {
|
|
46
54
|
return `${color('label', `${label}:`, { stream })} ${color(valueStyle, value, { stream })}`;
|
|
47
55
|
}
|
|
48
56
|
|
|
49
|
-
export function colorStatusWord(word, { stream = process.stderr } = {}) {
|
|
57
|
+
export function colorStatusWord(word: string, { stream = process.stderr }: { stream?: NodeJS.WriteStream } = {}): string {
|
|
50
58
|
const normalized = String(word || '').toLowerCase();
|
|
51
59
|
if (['up', 'ready', 'yes', 'pass', 'running', 'present', 'healthy'].includes(normalized)) {
|
|
52
60
|
return color('ok', word, { stream });
|
|
@@ -60,7 +68,7 @@ export function colorStatusWord(word, { stream = process.stderr } = {}) {
|
|
|
60
68
|
return color('info', word, { stream });
|
|
61
69
|
}
|
|
62
70
|
|
|
63
|
-
export function classifyLogEvent(event) {
|
|
71
|
+
export function classifyLogEvent(event: string): string {
|
|
64
72
|
const text = String(event || '');
|
|
65
73
|
if (/Module build failed|^ERROR in |BUILD FAILED|compiled with [1-9][0-9]* error/iu.test(text)) {
|
|
66
74
|
return 'err';
|
|
@@ -77,8 +85,8 @@ export function classifyLogEvent(event) {
|
|
|
77
85
|
return 'info';
|
|
78
86
|
}
|
|
79
87
|
|
|
80
|
-
export function colorLogEvent(event, { latest = false, stream = process.stderr } = {}) {
|
|
88
|
+
export function colorLogEvent(event: string, { latest = false, stream = process.stderr }: { latest?: boolean; stream?: NodeJS.WriteStream } = {}): string {
|
|
81
89
|
const style = classifyLogEvent(event);
|
|
82
90
|
const painted = color(style === 'label' ? 'label' : style, event, { stream });
|
|
83
91
|
return latest ? color('active', painted, { stream }) : painted;
|
|
84
|
-
}
|
|
92
|
+
}
|
|
@@ -1,15 +1,26 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
/**
|
|
3
|
-
* cli-commands.
|
|
2
|
+
* cli-commands.ts — single source of truth for recipe CLI tab completion.
|
|
4
3
|
*/
|
|
5
4
|
import fs from 'node:fs';
|
|
6
5
|
import path from 'node:path';
|
|
7
6
|
import { fileURLToPath } from 'node:url';
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
interface CommandSpec {
|
|
9
|
+
name: string;
|
|
10
|
+
aliases?: string[];
|
|
11
|
+
desc?: string;
|
|
12
|
+
flags?: string[];
|
|
13
|
+
args?: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface CommandSpecMap {
|
|
17
|
+
shared: CommandSpec[];
|
|
18
|
+
extension: CommandSpec[];
|
|
19
|
+
mobile: CommandSpec[];
|
|
20
|
+
shim: CommandSpec[];
|
|
21
|
+
}
|
|
10
22
|
|
|
11
|
-
|
|
12
|
-
export const SPEC = {
|
|
23
|
+
export const SPEC: CommandSpecMap = {
|
|
13
24
|
shim: [
|
|
14
25
|
{ name: 'sync', desc: 'Copy fixture, write slot context, install harness', flags: ['--dry-run', '--no-install'] },
|
|
15
26
|
{ name: 'help', aliases: ['-h', '--help'], desc: 'Show usage' },
|
|
@@ -34,9 +45,7 @@ export const SPEC = {
|
|
|
34
45
|
{ name: 'ready', aliases: ['ensure-ready'], desc: 'Ensure one healthy extension home tab' },
|
|
35
46
|
{ name: 'watch', aliases: ['start-watch', 'watcher'], desc: 'Start/reuse webpack watcher', flags: ['--full', '-f'] },
|
|
36
47
|
{ name: 'stop', aliases: ['stop-watch', 'stop-watcher'], desc: 'Stop this checkout watcher' },
|
|
37
|
-
{ name: 'rebuild', aliases: ['reset', 'reopen', 'reload', 'browser', 'launch', 'full-launch', 'runtime-launch'], desc: 'Clean webpack + browser launch', flags: ['--json', '--dry-run', '--full'] },
|
|
38
|
-
{ name: 'refresh', aliases: ['build'], desc: 'Fast refresh with active watcher' },
|
|
39
|
-
{ name: 'refresh:once', aliases: ['refresh-once', 'build:once', 'build-once'], desc: 'One-shot refresh-build helper' },
|
|
48
|
+
{ name: 'rebuild', aliases: ['reset', 'reopen', 'reload', 'browser', 'launch', 'full-launch', 'runtime-launch', 'build', 'build:once', 'build-once', 'refresh-once'], desc: 'Clean webpack + browser launch', flags: ['--json', '--dry-run', '--full'] },
|
|
40
49
|
{ name: 'sidepanel', desc: 'Side panel helper', args: ['cycle', 'open', 'close', 'toggle', 'status'] },
|
|
41
50
|
{ name: 'prepare', flags: ['--target', '--cdp-port', '--runtime-dir', '--validate'] },
|
|
42
51
|
{ name: 'debug', args: ['page', 'worker'], flags: ['--json', '--no-open'] },
|
|
@@ -46,7 +55,6 @@ export const SPEC = {
|
|
|
46
55
|
{ name: 'android', desc: 'Start Metro + launch Android dev client' },
|
|
47
56
|
{ name: 'setup:ios', desc: 'iOS launch + wallet fixture setup' },
|
|
48
57
|
{ name: 'setup:android', desc: 'Android launch + wallet fixture setup' },
|
|
49
|
-
{ name: 'refresh', aliases: ['reload', 'relaunch'], desc: 'Refresh Metro + relaunch dev client' },
|
|
50
58
|
{ name: 'stop', desc: 'Stop Metro for this slot' },
|
|
51
59
|
{ name: 'app-status', aliases: ['bridge-status'], desc: 'Bridge/runtime status' },
|
|
52
60
|
{ name: 'route', aliases: ['get-route'], desc: 'Current navigation route' },
|
|
@@ -65,9 +73,9 @@ export const SPEC = {
|
|
|
65
73
|
|
|
66
74
|
const GLOBAL_FLAGS = ['--json', '--dry-run', '--full', '-f', '--help', '-h', '--no-open', '--no-color'];
|
|
67
75
|
|
|
68
|
-
function mergeCommands(adapter) {
|
|
69
|
-
const byName = new Map();
|
|
70
|
-
const add = (cmd) => {
|
|
76
|
+
function mergeCommands(adapter: string): CommandSpec[] {
|
|
77
|
+
const byName = new Map<string, CommandSpec & { aliases: string[]; flags: string[]; args: string[] }>();
|
|
78
|
+
const add = (cmd: CommandSpec) => {
|
|
71
79
|
const existing = byName.get(cmd.name);
|
|
72
80
|
if (!existing) {
|
|
73
81
|
byName.set(cmd.name, {
|
|
@@ -84,12 +92,12 @@ function mergeCommands(adapter) {
|
|
|
84
92
|
if (!existing.desc && cmd.desc) existing.desc = cmd.desc;
|
|
85
93
|
};
|
|
86
94
|
for (const cmd of SPEC.shared) add(cmd);
|
|
87
|
-
for (const cmd of SPEC[adapter] || []) add(cmd);
|
|
95
|
+
for (const cmd of SPEC[adapter as keyof CommandSpecMap] || []) add(cmd);
|
|
88
96
|
return [...byName.values()];
|
|
89
97
|
}
|
|
90
98
|
|
|
91
|
-
export function commandTokens(adapter, { includeAliases = true } = {}) {
|
|
92
|
-
const tokens = new Set();
|
|
99
|
+
export function commandTokens(adapter: string, { includeAliases = true }: { includeAliases?: boolean } = {}): string[] {
|
|
100
|
+
const tokens = new Set<string>();
|
|
93
101
|
for (const cmd of mergeCommands(adapter)) {
|
|
94
102
|
tokens.add(cmd.name);
|
|
95
103
|
if (includeAliases) for (const alias of cmd.aliases || []) tokens.add(alias);
|
|
@@ -97,8 +105,8 @@ export function commandTokens(adapter, { includeAliases = true } = {}) {
|
|
|
97
105
|
return [...tokens].sort();
|
|
98
106
|
}
|
|
99
107
|
|
|
100
|
-
export function shimCommandTokens() {
|
|
101
|
-
const tokens = new Set();
|
|
108
|
+
export function shimCommandTokens(): string[] {
|
|
109
|
+
const tokens = new Set<string>();
|
|
102
110
|
for (const cmd of SPEC.shim) {
|
|
103
111
|
tokens.add(cmd.name);
|
|
104
112
|
for (const alias of cmd.aliases || []) tokens.add(alias);
|
|
@@ -106,7 +114,7 @@ export function shimCommandTokens() {
|
|
|
106
114
|
return [...tokens].sort();
|
|
107
115
|
}
|
|
108
116
|
|
|
109
|
-
export function lookupCommand(adapter, token) {
|
|
117
|
+
export function lookupCommand(adapter: string, token: string): CommandSpec | null {
|
|
110
118
|
for (const cmd of mergeCommands(adapter)) {
|
|
111
119
|
if (cmd.name === token) return cmd;
|
|
112
120
|
if ((cmd.aliases || []).includes(token)) return cmd;
|
|
@@ -118,28 +126,27 @@ export function lookupCommand(adapter, token) {
|
|
|
118
126
|
return null;
|
|
119
127
|
}
|
|
120
128
|
|
|
121
|
-
export function flagsForPosition(adapter, commandToken) {
|
|
129
|
+
export function flagsForPosition(adapter: string, commandToken: string): string[] {
|
|
122
130
|
const cmd = lookupCommand(adapter, commandToken);
|
|
123
131
|
const flags = new Set(GLOBAL_FLAGS);
|
|
124
132
|
if (cmd) for (const flag of cmd.flags || []) flags.add(flag);
|
|
125
133
|
return [...flags].sort();
|
|
126
134
|
}
|
|
127
135
|
|
|
128
|
-
export function argsForPosition(adapter, commandToken, argIndex) {
|
|
136
|
+
export function argsForPosition(adapter: string, commandToken: string, argIndex: number): string[] {
|
|
129
137
|
const cmd = lookupCommand(adapter, commandToken);
|
|
130
138
|
if (!cmd?.args?.length) return [];
|
|
131
139
|
const value = cmd.args[Math.max(0, argIndex)];
|
|
132
140
|
return value ? [value] : cmd.args;
|
|
133
141
|
}
|
|
134
142
|
|
|
135
|
-
const RUN_RECIPE_DIRS = [
|
|
143
|
+
const RUN_RECIPE_DIRS: ((adapter: string, root: string) => string)[] = [
|
|
136
144
|
(adapter, root) => path.join(root, 'temp/recipe/harness', adapter, 'runner/recipes'),
|
|
137
145
|
(adapter, root) => path.join(root, 'temp/agentic/recipe-harness', adapter, 'runner/recipes'),
|
|
138
146
|
];
|
|
139
147
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const byBase = new Map();
|
|
148
|
+
export function listRunRecipes(adapter: string, root: string, cwd = process.cwd()): string[] {
|
|
149
|
+
const byBase = new Map<string, string>();
|
|
143
150
|
for (const resolveDir of RUN_RECIPE_DIRS) {
|
|
144
151
|
const dir = resolveDir(adapter, root);
|
|
145
152
|
if (!fs.existsSync(dir)) continue;
|
|
@@ -153,20 +160,20 @@ export function listRunRecipes(adapter, root, cwd = process.cwd()) {
|
|
|
153
160
|
.sort();
|
|
154
161
|
}
|
|
155
162
|
|
|
156
|
-
function usage() {
|
|
163
|
+
function usage(): void {
|
|
157
164
|
process.stderr.write(`Usage:
|
|
158
|
-
cli-commands
|
|
159
|
-
cli-commands
|
|
160
|
-
cli-commands
|
|
161
|
-
cli-commands
|
|
162
|
-
cli-commands
|
|
163
|
-
cli-commands
|
|
165
|
+
cli-commands dump --adapter extension|mobile|shim [--aliases]
|
|
166
|
+
cli-commands describe --adapter extension|mobile|shim
|
|
167
|
+
cli-commands flags --adapter <adapter> --command <name>
|
|
168
|
+
cli-commands args --adapter <adapter> --command <name> [--index <n>]
|
|
169
|
+
cli-commands run-recipes --adapter extension|mobile --root <repo> [--cwd <dir>]
|
|
170
|
+
cli-commands global-flags
|
|
164
171
|
`);
|
|
165
172
|
}
|
|
166
173
|
|
|
167
|
-
async function main() {
|
|
168
|
-
const { parseArgs } = await import('node:util');
|
|
169
|
-
const { values, positionals } =
|
|
174
|
+
async function main(): Promise<void> {
|
|
175
|
+
const { parseArgs: parseArgsUtil } = await import('node:util');
|
|
176
|
+
const { values, positionals } = parseArgsUtil({
|
|
170
177
|
allowPositionals: true,
|
|
171
178
|
args: process.argv.slice(2),
|
|
172
179
|
options: {
|
|
@@ -197,12 +204,12 @@ async function main() {
|
|
|
197
204
|
}
|
|
198
205
|
|
|
199
206
|
if (command === 'dump') {
|
|
200
|
-
process.stdout.write(`${commandTokens(adapter, { includeAliases: values.aliases }).join('\n')}\n`);
|
|
207
|
+
process.stdout.write(`${commandTokens(adapter as string, { includeAliases: values.aliases }).join('\n')}\n`);
|
|
201
208
|
return;
|
|
202
209
|
}
|
|
203
210
|
|
|
204
211
|
if (command === 'describe') {
|
|
205
|
-
const rows = adapter === 'shim' ? SPEC.shim : mergeCommands(adapter);
|
|
212
|
+
const rows = adapter === 'shim' ? SPEC.shim : mergeCommands(adapter as string);
|
|
206
213
|
for (const cmd of rows) {
|
|
207
214
|
const aliases = (cmd.aliases || []).join('|');
|
|
208
215
|
const label = aliases ? `${cmd.name}|${aliases}` : cmd.name;
|
|
@@ -212,20 +219,20 @@ async function main() {
|
|
|
212
219
|
}
|
|
213
220
|
|
|
214
221
|
if (command === 'flags') {
|
|
215
|
-
process.stdout.write(`${flagsForPosition(adapter, values.command || '').join('\n')}\n`);
|
|
222
|
+
process.stdout.write(`${flagsForPosition(adapter as string, values.command || '').join('\n')}\n`);
|
|
216
223
|
return;
|
|
217
224
|
}
|
|
218
225
|
|
|
219
226
|
if (command === 'args') {
|
|
220
|
-
const index = Number.parseInt(values.index, 10) || 0;
|
|
221
|
-
process.stdout.write(`${argsForPosition(adapter, values.command || '', index).join('\n')}\n`);
|
|
227
|
+
const index = Number.parseInt(values.index as string, 10) || 0;
|
|
228
|
+
process.stdout.write(`${argsForPosition(adapter as string, values.command || '', index).join('\n')}\n`);
|
|
222
229
|
return;
|
|
223
230
|
}
|
|
224
231
|
|
|
225
232
|
if (command === 'run-recipes') {
|
|
226
233
|
const root = values.root ? path.resolve(values.root) : process.cwd();
|
|
227
234
|
const cwd = values.cwd ? path.resolve(values.cwd) : process.cwd();
|
|
228
|
-
process.stdout.write(`${listRunRecipes(adapter, root, cwd).join('\n')}\n`);
|
|
235
|
+
process.stdout.write(`${listRunRecipes(adapter as string, root, cwd).join('\n')}\n`);
|
|
229
236
|
return;
|
|
230
237
|
}
|
|
231
238
|
|
|
@@ -233,11 +240,11 @@ async function main() {
|
|
|
233
240
|
process.exit(2);
|
|
234
241
|
}
|
|
235
242
|
|
|
236
|
-
const
|
|
237
|
-
const
|
|
238
|
-
if (
|
|
239
|
-
main().catch((error) => {
|
|
243
|
+
const _filename = fileURLToPath(import.meta.url);
|
|
244
|
+
const isMain = process.argv[1] && path.resolve(process.argv[1]) === _filename;
|
|
245
|
+
if (isMain) {
|
|
246
|
+
main().catch((error: unknown) => {
|
|
240
247
|
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
241
248
|
process.exit(1);
|
|
242
249
|
});
|
|
243
|
-
}
|
|
250
|
+
}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
/**
|
|
3
|
-
* cli-version.
|
|
2
|
+
* cli-version.ts — detect stale installed harness scripts vs the active runner.
|
|
4
3
|
*/
|
|
5
4
|
import fs from 'node:fs';
|
|
6
5
|
import path from 'node:path';
|
|
7
6
|
import { spawnSync } from 'node:child_process';
|
|
8
7
|
import { parseArgs } from 'node:util';
|
|
9
8
|
|
|
10
|
-
function readJson(file) {
|
|
9
|
+
function readJson(file: string): unknown {
|
|
11
10
|
try {
|
|
12
11
|
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
13
12
|
} catch {
|
|
@@ -15,31 +14,49 @@ function readJson(file) {
|
|
|
15
14
|
}
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
function readPackageVersion(dir) {
|
|
17
|
+
function readPackageVersion(dir: string): string {
|
|
19
18
|
try {
|
|
20
|
-
const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8'));
|
|
19
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8')) as { version?: string };
|
|
21
20
|
return pkg.version || 'unknown';
|
|
22
21
|
} catch {
|
|
23
22
|
return 'unknown';
|
|
24
23
|
}
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
function gitHead(dir) {
|
|
26
|
+
function gitHead(dir: string): string {
|
|
28
27
|
const result = spawnSync('git', ['-C', dir, 'rev-parse', 'HEAD'], { encoding: 'utf8' });
|
|
29
28
|
return result.status === 0 ? result.stdout.trim() : 'unknown';
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
interface HarnessCheckInput {
|
|
32
|
+
runnerRoot: string;
|
|
33
|
+
manifestPath: string;
|
|
34
|
+
installedShaPath?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface HarnessCheckResult {
|
|
38
|
+
stale: boolean;
|
|
39
|
+
reasons: string[];
|
|
40
|
+
installedRevision?: string | null;
|
|
41
|
+
currentRevision?: string;
|
|
42
|
+
installedVersion?: string | null;
|
|
43
|
+
currentVersion?: string;
|
|
44
|
+
manifest?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function checkHarness({ runnerRoot, manifestPath }: HarnessCheckInput): HarnessCheckResult {
|
|
33
48
|
const manifest = readJson(manifestPath);
|
|
34
|
-
const reasons = [];
|
|
49
|
+
const reasons: string[] = [];
|
|
35
50
|
if (!manifest) {
|
|
36
51
|
return { stale: false, reasons: ['no harness manifest'] };
|
|
37
52
|
}
|
|
38
53
|
|
|
39
54
|
const currentRevision = gitHead(runnerRoot);
|
|
40
55
|
const currentVersion = readPackageVersion(runnerRoot);
|
|
41
|
-
const
|
|
42
|
-
const
|
|
56
|
+
const manifestRecord = manifest as Record<string, unknown>;
|
|
57
|
+
const source = manifestRecord.source as Record<string, unknown> | undefined;
|
|
58
|
+
const installedRevision = (source?.runnerRevision as string) || null;
|
|
59
|
+
const installedVersion = (manifestRecord.runnerPackageVersion as string) || null;
|
|
43
60
|
|
|
44
61
|
if (installedRevision && installedRevision !== 'unknown' && installedRevision !== currentRevision) {
|
|
45
62
|
reasons.push(`runner revision ${installedRevision.slice(0, 8)} != ${currentRevision.slice(0, 8)}`);
|
|
@@ -58,12 +75,12 @@ export function checkHarness({ runnerRoot, manifestPath, installedShaPath }) {
|
|
|
58
75
|
};
|
|
59
76
|
}
|
|
60
77
|
|
|
61
|
-
function usage() {
|
|
78
|
+
function usage(): void {
|
|
62
79
|
console.error(`Usage:
|
|
63
|
-
cli-version
|
|
80
|
+
cli-version check --runner-root <dir> --manifest <path> [--installed-sha <path>] [--json]`);
|
|
64
81
|
}
|
|
65
82
|
|
|
66
|
-
async function main() {
|
|
83
|
+
async function main(): Promise<void> {
|
|
67
84
|
const [command, ...rest] = process.argv.slice(2);
|
|
68
85
|
const { values } = parseArgs({
|
|
69
86
|
args: rest,
|
|
@@ -93,7 +110,7 @@ async function main() {
|
|
|
93
110
|
process.exit(2);
|
|
94
111
|
}
|
|
95
112
|
|
|
96
|
-
const payload = {
|
|
113
|
+
const payload: HarnessCheckResult & { manifest: string } = {
|
|
97
114
|
...checkHarness({
|
|
98
115
|
runnerRoot,
|
|
99
116
|
manifestPath,
|
|
@@ -115,9 +132,10 @@ async function main() {
|
|
|
115
132
|
process.stdout.write('harness up to date\n');
|
|
116
133
|
}
|
|
117
134
|
|
|
118
|
-
|
|
119
|
-
|
|
135
|
+
const isMain = process.argv[1] && path.resolve(process.argv[1]) === path.resolve(import.meta.filename ?? '');
|
|
136
|
+
if (isMain) {
|
|
137
|
+
main().catch((error: unknown) => {
|
|
120
138
|
console.error(error instanceof Error ? error.message : String(error));
|
|
121
139
|
process.exit(1);
|
|
122
140
|
});
|
|
123
|
-
}
|
|
141
|
+
}
|
|
@@ -23,10 +23,10 @@ import {
|
|
|
23
23
|
checkHealBounds,
|
|
24
24
|
} from './heal-bounds.ts';
|
|
25
25
|
import type { HealPolicy, HealState, HealBoundViolation } from './heal-bounds.ts';
|
|
26
|
-
import { ensureExtensionReady } from '
|
|
27
|
-
import { resolveExtensionId } from '
|
|
28
|
-
import { decideExtensionReadiness } from '
|
|
29
|
-
import { decideMobileReadiness } from '
|
|
26
|
+
import { ensureExtensionReady } from './adapters/extension/ensure-ready.ts';
|
|
27
|
+
import { resolveExtensionId } from './adapters/extension/extension-id.ts';
|
|
28
|
+
import { decideExtensionReadiness } from './adapters/extension/runtime-decision.ts';
|
|
29
|
+
import { decideMobileReadiness } from './adapters/mobile/runtime-decision.ts';
|
|
30
30
|
// NOTE: extension-runtime.ts loads the recipe harness at module scope, so it
|
|
31
31
|
// is imported LAZILY (dynamic import) only inside the handlers that drive a live
|
|
32
32
|
// runtime. Static-import it here and every command — manifest, doctor,
|
|
@@ -372,7 +372,7 @@ async function prepareRuntimeIfNeeded(
|
|
|
372
372
|
runtimeOptions: RuntimeOptions,
|
|
373
373
|
): Promise<void> {
|
|
374
374
|
if (adapter !== 'extension' || runtimeOptions.skipExtensionRuntimePrepare === true) return;
|
|
375
|
-
const { prepareExtensionRuntime } = await import('
|
|
375
|
+
const { prepareExtensionRuntime } = await import('./adapters/extension/runtime.ts');
|
|
376
376
|
await prepareExtensionRuntime({
|
|
377
377
|
projectRoot,
|
|
378
378
|
cdpPort: runtimeOptions.cdpPort,
|
|
@@ -390,7 +390,7 @@ function restoreEnv(key: string, value: string | undefined) {
|
|
|
390
390
|
async function runSelfTest(options: CliOptions) {
|
|
391
391
|
const root = optionString(options, 'artifactsDir')
|
|
392
392
|
? path.resolve(requiredOption(options, 'artifactsDir', 'self-test artifacts dir missing.'))
|
|
393
|
-
: await mkdtemp(path.join(os.tmpdir(), '
|
|
393
|
+
: await mkdtemp(path.join(os.tmpdir(), 'mm-harness-runner-'));
|
|
394
394
|
const previousAutoHud = process.env.METAMASK_RECIPE_AUTO_HUD;
|
|
395
395
|
const runs = [];
|
|
396
396
|
try {
|
|
@@ -596,7 +596,7 @@ async function handleRuntimeHealth({ options }: ParsedArgs): Promise<number> {
|
|
|
596
596
|
optionString(options, 'cdpPort') ?? process.env.CDP_PORT ?? process.env.RECIPE_CDP_PORT,
|
|
597
597
|
'runtime-health requires --cdp-port <port>.',
|
|
598
598
|
);
|
|
599
|
-
const { checkExtensionRuntimeHealth, formatHealthFailure } = await import('
|
|
599
|
+
const { checkExtensionRuntimeHealth, formatHealthFailure } = await import('./adapters/extension/runtime.ts');
|
|
600
600
|
const report = await checkExtensionRuntimeHealth(target, cdpPort);
|
|
601
601
|
if (optionFlag(options, 'json')) console.log(JSON.stringify(report, null, 2));
|
|
602
602
|
else if (report.status === 'PASS') console.log(`PASS extension runtime cdp=${cdpPort} target=${report.targetUrl}`);
|
|
@@ -645,7 +645,7 @@ async function handleRuntimeLaunch({ options }: ParsedArgs): Promise<number> {
|
|
|
645
645
|
cdpPort,
|
|
646
646
|
artifactsDir,
|
|
647
647
|
reason: 'harness_live_script_missing',
|
|
648
|
-
fix: `Run
|
|
648
|
+
fix: `Run mm-harness install --adapter extension --target ${shellQuote(target)}, then rerun: ${runtimeLaunchCommand(target, cdpPort, chromeUserDataDir)}`,
|
|
649
649
|
command,
|
|
650
650
|
});
|
|
651
651
|
printRuntimeLaunchReport(report, optionFlag(options, 'json'));
|
|
@@ -710,7 +710,7 @@ async function handleRuntimeLaunch({ options }: ParsedArgs): Promise<number> {
|
|
|
710
710
|
}
|
|
711
711
|
|
|
712
712
|
function runtimeLaunchCommand(target: string, cdpPort: number, chromeUserDataDir?: string, startWatch = false): string {
|
|
713
|
-
const base = `
|
|
713
|
+
const base = `mm-harness runtime-launch --adapter extension --target ${shellQuote(target)} --cdp-port ${cdpPort}`;
|
|
714
714
|
const withMode = startWatch ? `${base} --start-watch` : base;
|
|
715
715
|
return chromeUserDataDir ? `${withMode} --chrome-user-data-dir ${shellQuote(chromeUserDataDir)}` : withMode;
|
|
716
716
|
}
|
|
@@ -828,7 +828,7 @@ async function handleEnsureReady({ options }: ParsedArgs): Promise<number> {
|
|
|
828
828
|
// 5 validation failure (run, run --plan, call — adapter-aware validation errors).
|
|
829
829
|
const EXIT = { ok: 0, runtime: 1, usage: 2, infra: 3, bounded: 4, validation: 5 } as const;
|
|
830
830
|
|
|
831
|
-
// Typed exit-code error: carries exitCode so both the global catch (
|
|
831
|
+
// Typed exit-code error: carries exitCode so both the global catch (mm-harness bin)
|
|
832
832
|
// and the mm-harness delegate() wrapper classify the error correctly rather than always
|
|
833
833
|
// returning 1. Usage errors (bad args / unsupported flags) carry EXIT.usage (2);
|
|
834
834
|
// validation errors carry EXIT.validation (5). Never throw a plain new Error() for
|
|
@@ -1184,7 +1184,7 @@ async function handleCall(argv: string[]): Promise<number> {
|
|
|
1184
1184
|
heal,
|
|
1185
1185
|
state,
|
|
1186
1186
|
);
|
|
1187
|
-
if (violation !== null) return emitHealViolation(json, 'call', result, violation, state);
|
|
1187
|
+
if (violation !== null) return emitHealViolation(json, 'call', result, violation, state, adapter);
|
|
1188
1188
|
|
|
1189
1189
|
if (json) {
|
|
1190
1190
|
console.log(
|
|
@@ -1286,7 +1286,7 @@ function synthesizeOneNodeRecipe(action: string, args: Record<string, string>):
|
|
|
1286
1286
|
|
|
1287
1287
|
// Reusable one-node engine path (the same machinery `call` uses), exposed so
|
|
1288
1288
|
// `fixtures set` can apply the canonical wallet fixture through the real engine on
|
|
1289
|
-
// the extension (which has no standalone
|
|
1289
|
+
// the extension (which has no standalone shell set arm).
|
|
1290
1290
|
async function runOneNode(
|
|
1291
1291
|
adapter: MetaMaskRecipeAdapter,
|
|
1292
1292
|
action: string,
|
|
@@ -1520,7 +1520,7 @@ async function handleRun({ positional, options }: ParsedArgs): Promise<number> {
|
|
|
1520
1520
|
heal,
|
|
1521
1521
|
state,
|
|
1522
1522
|
);
|
|
1523
|
-
if (violation !== null) return emitHealViolation(json, 'run', result, violation, state);
|
|
1523
|
+
if (violation !== null) return emitHealViolation(json, 'run', result, violation, state, adapter);
|
|
1524
1524
|
const exitCode = result.status === 'pass' ? EXIT.ok : EXIT.runtime;
|
|
1525
1525
|
if (json) {
|
|
1526
1526
|
// mm-harness envelope (matches launch/verify/doctor): the engine's result is
|
|
@@ -1619,7 +1619,14 @@ function emitHealViolation(
|
|
|
1619
1619
|
result: RecipeRunResult,
|
|
1620
1620
|
violation: HealBoundViolation,
|
|
1621
1621
|
state: HealState,
|
|
1622
|
+
adapter?: MetaMaskRecipeAdapter,
|
|
1622
1623
|
): number {
|
|
1624
|
+
// core is headless: `fixtures set` is blocked. Teach the env-var / recipe-node
|
|
1625
|
+
// path instead so the user has a reachable next step.
|
|
1626
|
+
const userAction =
|
|
1627
|
+
adapter === 'core' && violation.code === 'WALLET_STATE_REQUIRED'
|
|
1628
|
+
? 'set MM_TEST_ACCOUNT_ADDRESS=<0x…> in env, or add "account": "<0x…>" to the node block in the recipe'
|
|
1629
|
+
: violation.userAction;
|
|
1623
1630
|
if (json) {
|
|
1624
1631
|
console.log(
|
|
1625
1632
|
JSON.stringify(
|
|
@@ -1639,7 +1646,7 @@ function emitHealViolation(
|
|
|
1639
1646
|
code: violation.code,
|
|
1640
1647
|
message: violation.message,
|
|
1641
1648
|
retryable: false,
|
|
1642
|
-
userAction:
|
|
1649
|
+
userAction: userAction ?? null,
|
|
1643
1650
|
originalError: violation.originalError ?? null,
|
|
1644
1651
|
},
|
|
1645
1652
|
},
|
|
@@ -1651,7 +1658,7 @@ function emitHealViolation(
|
|
|
1651
1658
|
console.error(
|
|
1652
1659
|
`✗ mm-harness ${command}: ${violation.message}` +
|
|
1653
1660
|
(violation.originalError ? `\n --- original failure ---\n${violation.originalError}` : '') +
|
|
1654
|
-
(
|
|
1661
|
+
(userAction ? `\n Next: ${userAction}` : ''),
|
|
1655
1662
|
);
|
|
1656
1663
|
}
|
|
1657
1664
|
return violation.exitCode;
|
|
@@ -1792,7 +1799,7 @@ export async function main(argv: string[]): Promise<number> {
|
|
|
1792
1799
|
}
|
|
1793
1800
|
return code;
|
|
1794
1801
|
}
|
|
1795
|
-
// launch/logs/debug/fixtures compose
|
|
1802
|
+
// launch/logs/debug/fixtures compose adapter scripts directly and own policy,
|
|
1796
1803
|
// healing, teaching, and the --json contract.
|
|
1797
1804
|
if (command === 'launch') return handleLaunch(argv.slice(1));
|
|
1798
1805
|
if (command === 'logs') return handleLogs(argv.slice(1));
|
|
@@ -1803,8 +1810,8 @@ export async function main(argv: string[]): Promise<number> {
|
|
|
1803
1810
|
return handler(parseArgs(argv.slice(1), command));
|
|
1804
1811
|
}
|
|
1805
1812
|
|
|
1806
|
-
// Auto-run only when this file IS the process entry (
|
|
1807
|
-
//
|
|
1813
|
+
// Auto-run only when this file IS the process entry (bin/mm-harness execs it
|
|
1814
|
+
// directly). The commander front (`src/mm-harness-cli.ts`) sets this flag
|
|
1808
1815
|
// before importing so it can reuse `main` without triggering a second dispatch.
|
|
1809
1816
|
if (!(globalThis as Record<string, unknown>).__MM_HARNESS_WRAPPER__) {
|
|
1810
1817
|
try {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// debug — open the debug console by composing open-debug.mjs directly:
|
|
2
|
+
// extension `debug` (--worker → service-worker target); mobile `debug`
|
|
3
|
+
// (--dev-menu → developer menu). Cross-platform flag misuse teaches (exit 2).
|
|
4
|
+
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
|
|
7
|
+
import { runnerDir } from '../paths.ts';
|
|
8
|
+
import { EXIT, flag, parseFlags, resolveAdapter, spawnScript, targetOf, usageOut } from './shared.ts';
|
|
9
|
+
|
|
10
|
+
const DEBUG_BOOLEANS = new Set(['worker', 'devMenu', 'json']);
|
|
11
|
+
|
|
12
|
+
export async function handleDebug(argv: string[]): Promise<number> {
|
|
13
|
+
const { options } = parseFlags(argv, DEBUG_BOOLEANS);
|
|
14
|
+
const json = flag(options, 'json');
|
|
15
|
+
const target = targetOf(options);
|
|
16
|
+
const adapter = resolveAdapter(options, target);
|
|
17
|
+
|
|
18
|
+
if (!adapter) return usageOut(json, 'debug', `could not detect the MetaMask repo type for ${target}`);
|
|
19
|
+
if (adapter === 'core') return usageOut(json, 'debug', 'core is headless; there is no debug console.');
|
|
20
|
+
|
|
21
|
+
const worker = flag(options, 'worker');
|
|
22
|
+
const devMenu = flag(options, 'devMenu');
|
|
23
|
+
if (adapter === 'mobile' && worker) {
|
|
24
|
+
return usageOut(
|
|
25
|
+
json,
|
|
26
|
+
'debug',
|
|
27
|
+
'--worker is extension-only (service-worker DevTools). Use --dev-menu on mobile.\n Next: mm-harness debug --dev-menu',
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
if (adapter === 'extension' && devMenu) {
|
|
31
|
+
return usageOut(
|
|
32
|
+
json,
|
|
33
|
+
'debug',
|
|
34
|
+
'--dev-menu is mobile-only (RN developer menu). Use --worker on the extension.\n Next: mm-harness debug --worker',
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const openDebug = path.join(runnerDir, 'adapters/shared/open-debug.mjs');
|
|
39
|
+
const debugArgs: string[] = ['--adapter', adapter];
|
|
40
|
+
|
|
41
|
+
if (adapter === 'extension') {
|
|
42
|
+
if (process.env.CDP_PORT) debugArgs.push('--cdp-port', process.env.CDP_PORT);
|
|
43
|
+
debugArgs.push('--target', worker ? 'worker' : 'page');
|
|
44
|
+
} else {
|
|
45
|
+
if (process.env.WATCHER_PORT) debugArgs.push('--port', process.env.WATCHER_PORT);
|
|
46
|
+
debugArgs.push('--action', devMenu ? 'dev-menu' : 'debug');
|
|
47
|
+
}
|
|
48
|
+
if (json) debugArgs.push('--json');
|
|
49
|
+
|
|
50
|
+
const result = spawnScript(process.execPath, [openDebug, ...debugArgs], target, json);
|
|
51
|
+
if (json) {
|
|
52
|
+
console.log(
|
|
53
|
+
JSON.stringify(
|
|
54
|
+
{ schemaVersion: 1, command: 'debug', adapter, mode: worker ? 'worker' : devMenu ? 'dev-menu' : 'default', exitCode: result.status === 0 ? EXIT.ok : EXIT.runtime },
|
|
55
|
+
null,
|
|
56
|
+
2,
|
|
57
|
+
),
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return result.status === 0 ? EXIT.ok : EXIT.runtime;
|
|
61
|
+
}
|