@deeeed/metamask-harness 0.78.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 +55 -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/ensure-runner-deps.sh +2 -2
- package/adapters/shared/harness-source-fingerprint.mjs +13 -8
- package/adapters/shared/open-debug.mjs +2 -2
- package/adapters/shared/runner-deps-ready.mjs +1 -1
- package/adapters/shared/sync-wallet-fixture.sh +8 -5
- package/adapters/terminal/cleanup.mjs +2 -1
- package/adapters/terminal/inject.mjs +2 -1
- package/adapters/terminal/lib/cdp-client.mjs +1 -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 +3 -3
- package/dist/adapters/core/surface.js +22 -5
- 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 +3 -2
- package/dist/adapters/extension/runtime.js +9 -5
- package/dist/adapters/extension/surface.js +20 -5
- 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 +4 -5
- 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 +9 -8
- package/dist/adapters/mobile/runtime-decision.js +5 -7
- package/dist/adapters/mobile/source-freshness.js +22 -126
- package/dist/adapters/mobile/surface.js +31 -6
- 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/registry.js +2 -14
- 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 +12 -4
- 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 +3 -9
- 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 +6 -11
- 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/discovery.js +1 -1
- package/dist/doctor.js +3 -4
- 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 +48 -78
- package/dist/performance-observation.js +2 -2
- package/dist/progress.js +1 -1
- package/dist/recipe-assistance-context.js +2 -4
- package/dist/recipe-security.js +2 -59
- package/dist/review/knowledge.js +3 -3
- package/dist/runner.js +5 -3
- package/dist/runtime-context.js +1 -1
- package/dist/task-view.js +3 -4
- package/docs/CONTRIBUTING.md +3 -3
- package/docs/cli-contract.md +2 -2
- package/docs/feature-guard.md +90 -0
- package/library/README.md +3 -1
- package/library/actions/core/perps/_controller.mjs +153 -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 -8
- 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
|
@@ -1,292 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Operator slot title for headed extension Chrome.
|
|
5
|
-
*
|
|
6
|
-
* Chrome's window label is the active tab's document.title. Farmslot stamps
|
|
7
|
-
* home.html to "<slot-id> — MetaMask" so operators can tell which slot owns a
|
|
8
|
-
* window when several farms run side by side.
|
|
9
|
-
*
|
|
10
|
-
* Stamping is best-effort: missing slot context or an uninspectable tab must
|
|
11
|
-
* never fail launch/readiness. A MutationObserver keeps the prefix across
|
|
12
|
-
* MetaMask SPA title resets.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const fs = require('node:fs');
|
|
16
|
-
const http = require('node:http');
|
|
17
|
-
const path = require('node:path');
|
|
18
|
-
|
|
19
|
-
function sanitizeSlotId(value) {
|
|
20
|
-
const slotId = typeof value === 'string' ? value.trim() : '';
|
|
21
|
-
return /^[A-Za-z0-9._:-]{1,64}$/u.test(slotId) ? slotId : '';
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function readSlotId(target, runtimeDir) {
|
|
25
|
-
for (const key of ['RECIPE_SLOT_ID', 'SLOT_ID', 'FARMSLOT_SLOT_ID']) {
|
|
26
|
-
const value = sanitizeSlotId(process.env[key]);
|
|
27
|
-
if (value) return value;
|
|
28
|
-
}
|
|
29
|
-
if (!target || !runtimeDir) return '';
|
|
30
|
-
try {
|
|
31
|
-
const runtimeContext = JSON.parse(
|
|
32
|
-
fs.readFileSync(path.join(target, runtimeDir, 'agentic-runtime.json'), 'utf8'),
|
|
33
|
-
);
|
|
34
|
-
return sanitizeSlotId(runtimeContext.slotId);
|
|
35
|
-
} catch {
|
|
36
|
-
// Standalone harness users do not need a custom browser title.
|
|
37
|
-
return '';
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Serialized page-evaluation callback. Must stay a plain function (no closure).
|
|
43
|
-
*/
|
|
44
|
-
function applyPersistentSlotTitle(slot) {
|
|
45
|
-
// Inline sanitize because the serialized function cannot call Node helpers.
|
|
46
|
-
const id =
|
|
47
|
-
typeof slot === 'string' && /^[A-Za-z0-9._:-]{1,64}$/u.test(slot.trim())
|
|
48
|
-
? slot.trim()
|
|
49
|
-
: '';
|
|
50
|
-
if (!id) return document.title;
|
|
51
|
-
window.__farmslotSlotId = id;
|
|
52
|
-
|
|
53
|
-
const stripSlotPrefixes = (title) => {
|
|
54
|
-
let base = String(title || 'MetaMask');
|
|
55
|
-
// Accept em dash, en dash, or hyphen — historical stampers mixed them.
|
|
56
|
-
for (let i = 0; i < 32; i += 1) {
|
|
57
|
-
const stripped = base.replace(/^.+?\s+[—–-]\s+/u, '');
|
|
58
|
-
if (stripped === base) break;
|
|
59
|
-
base = stripped;
|
|
60
|
-
}
|
|
61
|
-
return base || 'MetaMask';
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const desiredTitle = () => {
|
|
65
|
-
const id = window.__farmslotSlotId;
|
|
66
|
-
if (!id) return document.title;
|
|
67
|
-
return `${id} — ${stripSlotPrefixes(document.title)}`;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const setTitle = () => {
|
|
71
|
-
if (window.__farmslotSlotTitleLock) {
|
|
72
|
-
window.__farmslotSlotTitlePending = true;
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
const next = desiredTitle();
|
|
76
|
-
if (document.title === next) return;
|
|
77
|
-
window.__farmslotSlotTitleLock = true;
|
|
78
|
-
try {
|
|
79
|
-
document.title = next;
|
|
80
|
-
} finally {
|
|
81
|
-
// Release after the title mutation is delivered so the observer cannot
|
|
82
|
-
// re-enter and stack prefixes while React also mutates the DOM. If a
|
|
83
|
-
// mutation arrived while locked, re-apply once after unlock.
|
|
84
|
-
queueMicrotask(() => {
|
|
85
|
-
window.__farmslotSlotTitleLock = false;
|
|
86
|
-
if (window.__farmslotSlotTitlePending) {
|
|
87
|
-
window.__farmslotSlotTitlePending = false;
|
|
88
|
-
setTitle();
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
setTitle();
|
|
95
|
-
if (!window.__farmslotSlotTitleObserver) {
|
|
96
|
-
let node = document.querySelector('title');
|
|
97
|
-
if (!node) {
|
|
98
|
-
node = document.createElement('title');
|
|
99
|
-
(document.head || document.documentElement).appendChild(node);
|
|
100
|
-
}
|
|
101
|
-
window.__farmslotSlotTitleObserver = new MutationObserver(setTitle);
|
|
102
|
-
// Observe only the <title> element — watching head/documentElement with
|
|
103
|
-
// subtree:true re-fires on every React DOM mutation and can livelock CDP.
|
|
104
|
-
window.__farmslotSlotTitleObserver.observe(node, {
|
|
105
|
-
childList: true,
|
|
106
|
-
characterData: true,
|
|
107
|
-
subtree: true,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
return document.title;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function buildStampExpression(slotId) {
|
|
114
|
-
const slot = sanitizeSlotId(slotId);
|
|
115
|
-
if (!slot) return 'document.title';
|
|
116
|
-
// Single source of truth: serialize the Playwright callback for CDP evaluate.
|
|
117
|
-
return `(${applyPersistentSlotTitle.toString()})(${JSON.stringify(slot)})`;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function assertLocalUrl(url) {
|
|
121
|
-
if (!/^http:\/\/127\.0\.0\.1:\d+\//u.test(url)) {
|
|
122
|
-
throw new Error(`slot-title: refusing non-local URL: ${url}`);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function assertLocalWebSocketUrl(url) {
|
|
127
|
-
if (!/^ws:\/\/(?:127\.0\.0\.1|localhost):\d+\//u.test(String(url))) {
|
|
128
|
-
throw new Error(`slot-title: refusing non-local websocket URL: ${url}`);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function httpJson(url, timeoutMs = 3000) {
|
|
133
|
-
assertLocalUrl(url);
|
|
134
|
-
return new Promise((resolve, reject) => {
|
|
135
|
-
const req = http.get(url, (res) => {
|
|
136
|
-
let data = '';
|
|
137
|
-
res.setEncoding('utf8');
|
|
138
|
-
res.on('data', (chunk) => {
|
|
139
|
-
data += chunk;
|
|
140
|
-
});
|
|
141
|
-
res.on('end', () => {
|
|
142
|
-
try {
|
|
143
|
-
resolve(JSON.parse(data));
|
|
144
|
-
} catch (err) {
|
|
145
|
-
reject(new Error(`invalid JSON from ${url}: ${err.message}`));
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
req.setTimeout(timeoutMs, () => {
|
|
150
|
-
req.destroy(new Error(`timeout from ${url}`));
|
|
151
|
-
});
|
|
152
|
-
req.on('error', reject);
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function resolveWebSocket(target) {
|
|
157
|
-
try {
|
|
158
|
-
// Prefer the target checkout's ws, then the harness install.
|
|
159
|
-
const { createRequire } = require('node:module');
|
|
160
|
-
const req = createRequire(__filename);
|
|
161
|
-
if (target) {
|
|
162
|
-
try {
|
|
163
|
-
return req(req.resolve('ws', { paths: [target] }));
|
|
164
|
-
} catch {
|
|
165
|
-
// Fall through to harness / global.
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
return req('ws');
|
|
169
|
-
} catch {
|
|
170
|
-
return typeof WebSocket === 'function' ? WebSocket : null;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
async function cdpEvaluate(target, webSocketDebuggerUrl, expression, timeoutMs = 5000) {
|
|
175
|
-
assertLocalWebSocketUrl(webSocketDebuggerUrl);
|
|
176
|
-
const WebSocketImpl = resolveWebSocket(target);
|
|
177
|
-
if (!WebSocketImpl) return { skipped: true, reason: 'WebSocket unavailable' };
|
|
178
|
-
return new Promise((resolve, reject) => {
|
|
179
|
-
const ws = new WebSocketImpl(webSocketDebuggerUrl);
|
|
180
|
-
const timer = setTimeout(() => {
|
|
181
|
-
try {
|
|
182
|
-
ws.close();
|
|
183
|
-
} catch {
|
|
184
|
-
// Best-effort timeout cleanup.
|
|
185
|
-
}
|
|
186
|
-
reject(new Error('timeout evaluating extension page via CDP'));
|
|
187
|
-
}, timeoutMs);
|
|
188
|
-
const onOpen = () => {
|
|
189
|
-
ws.send(
|
|
190
|
-
JSON.stringify({
|
|
191
|
-
id: 1,
|
|
192
|
-
method: 'Runtime.evaluate',
|
|
193
|
-
params: { expression, awaitPromise: true, returnByValue: true },
|
|
194
|
-
}),
|
|
195
|
-
);
|
|
196
|
-
};
|
|
197
|
-
const onMessage = (event) => {
|
|
198
|
-
const raw = event?.data ?? event;
|
|
199
|
-
const msg = JSON.parse(Buffer.isBuffer(raw) ? raw.toString('utf8') : String(raw));
|
|
200
|
-
if (msg.id !== 1) return;
|
|
201
|
-
clearTimeout(timer);
|
|
202
|
-
ws.close();
|
|
203
|
-
if (msg.error) {
|
|
204
|
-
reject(new Error(msg.error.message || JSON.stringify(msg.error)));
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
resolve(msg.result?.result?.value ?? null);
|
|
208
|
-
};
|
|
209
|
-
const onError = (err) => {
|
|
210
|
-
clearTimeout(timer);
|
|
211
|
-
reject(new Error(`CDP websocket error while stamping slot title: ${err?.message || err || 'unknown'}`));
|
|
212
|
-
};
|
|
213
|
-
if (typeof ws.on === 'function') {
|
|
214
|
-
ws.on('open', onOpen);
|
|
215
|
-
ws.on('message', onMessage);
|
|
216
|
-
ws.on('error', onError);
|
|
217
|
-
} else {
|
|
218
|
-
ws.addEventListener('open', onOpen);
|
|
219
|
-
ws.addEventListener('message', onMessage);
|
|
220
|
-
ws.addEventListener('error', onError);
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function isHomePage(target, extensionId) {
|
|
226
|
-
if (!target || target.type !== 'page' || typeof target.url !== 'string') return false;
|
|
227
|
-
if (!target.url.startsWith(`chrome-extension://${extensionId}/`)) return false;
|
|
228
|
-
return target.url.includes('/home.html');
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Stamp every inspectable home.html tab for this extension over CDP.
|
|
233
|
-
* Attached tabs (no webSocketDebuggerUrl) are skipped — another client owns them.
|
|
234
|
-
*/
|
|
235
|
-
async function stampHomeTabsViaCdp(options) {
|
|
236
|
-
const {
|
|
237
|
-
target = process.cwd(),
|
|
238
|
-
cdpPort,
|
|
239
|
-
extensionId,
|
|
240
|
-
slotId: slotIdOption,
|
|
241
|
-
runtimeDir,
|
|
242
|
-
} = options || {};
|
|
243
|
-
const slotId = sanitizeSlotId(slotIdOption) || readSlotId(target, runtimeDir);
|
|
244
|
-
const empty = { slotId: slotId || '', stamped: 0, skipped: 0, titles: [] };
|
|
245
|
-
if (!slotId || !cdpPort || !extensionId) return empty;
|
|
246
|
-
|
|
247
|
-
let targets;
|
|
248
|
-
try {
|
|
249
|
-
targets = await httpJson(`http://127.0.0.1:${cdpPort}/json/list`);
|
|
250
|
-
} catch {
|
|
251
|
-
return empty;
|
|
252
|
-
}
|
|
253
|
-
if (!Array.isArray(targets)) return empty;
|
|
254
|
-
|
|
255
|
-
const homes = targets.filter((t) => isHomePage(t, extensionId));
|
|
256
|
-
const titles = [];
|
|
257
|
-
let stamped = 0;
|
|
258
|
-
let skipped = 0;
|
|
259
|
-
const expression = buildStampExpression(slotId);
|
|
260
|
-
|
|
261
|
-
for (const home of homes) {
|
|
262
|
-
if (typeof home.webSocketDebuggerUrl !== 'string') {
|
|
263
|
-
skipped += 1;
|
|
264
|
-
continue;
|
|
265
|
-
}
|
|
266
|
-
try {
|
|
267
|
-
const title = await cdpEvaluate(target, home.webSocketDebuggerUrl, expression);
|
|
268
|
-
if (title && typeof title === 'object' && title.skipped) {
|
|
269
|
-
skipped += 1;
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
if (typeof title === 'string') {
|
|
273
|
-
titles.push(title);
|
|
274
|
-
stamped += 1;
|
|
275
|
-
} else {
|
|
276
|
-
skipped += 1;
|
|
277
|
-
}
|
|
278
|
-
} catch {
|
|
279
|
-
skipped += 1;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
return { slotId, stamped, skipped, titles };
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
module.exports = {
|
|
287
|
-
sanitizeSlotId,
|
|
288
|
-
readSlotId,
|
|
289
|
-
applyPersistentSlotTitle,
|
|
290
|
-
buildStampExpression,
|
|
291
|
-
stampHomeTabsViaCdp,
|
|
292
|
-
};
|