@monoes/monobrowse 1.0.5 → 1.0.7
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/README.md +68 -0
- package/dist/src/__tests__/adapters.test.d.ts +2 -0
- package/dist/src/__tests__/adapters.test.d.ts.map +1 -0
- package/dist/src/__tests__/adapters.test.js +104 -0
- package/dist/src/__tests__/adapters.test.js.map +1 -0
- package/dist/src/__tests__/batch-eval-parsing.test.d.ts +0 -0
- package/dist/src/__tests__/batch-eval-parsing.test.d.ts.map +0 -0
- package/dist/src/__tests__/batch-eval-parsing.test.js +0 -0
- package/dist/src/__tests__/batch-eval-parsing.test.js.map +0 -0
- package/dist/src/__tests__/box-model.test.d.ts +2 -0
- package/dist/src/__tests__/box-model.test.d.ts.map +1 -0
- package/dist/src/__tests__/box-model.test.js +36 -0
- package/dist/src/__tests__/box-model.test.js.map +1 -0
- package/dist/src/__tests__/browser-launch.test.d.ts +0 -0
- package/dist/src/__tests__/browser-launch.test.d.ts.map +0 -0
- package/dist/src/__tests__/browser-launch.test.js +0 -0
- package/dist/src/__tests__/browser-launch.test.js.map +0 -0
- package/dist/src/__tests__/cdp-client.test.d.ts +2 -0
- package/dist/src/__tests__/cdp-client.test.d.ts.map +1 -0
- package/dist/src/__tests__/cdp-client.test.js +326 -0
- package/dist/src/__tests__/cdp-client.test.js.map +1 -0
- package/dist/src/__tests__/close-browser.test.d.ts +2 -0
- package/dist/src/__tests__/close-browser.test.d.ts.map +1 -0
- package/dist/src/__tests__/close-browser.test.js +128 -0
- package/dist/src/__tests__/close-browser.test.js.map +1 -0
- package/dist/src/__tests__/console-log.test.d.ts +2 -0
- package/dist/src/__tests__/console-log.test.d.ts.map +1 -0
- package/dist/src/__tests__/console-log.test.js +195 -0
- package/dist/src/__tests__/console-log.test.js.map +1 -0
- package/dist/src/__tests__/find.test.d.ts +2 -0
- package/dist/src/__tests__/find.test.d.ts.map +1 -0
- package/dist/src/__tests__/find.test.js +299 -0
- package/dist/src/__tests__/find.test.js.map +1 -0
- package/dist/src/__tests__/frame-command.test.d.ts +2 -0
- package/dist/src/__tests__/frame-command.test.d.ts.map +1 -0
- package/dist/src/__tests__/frame-command.test.js +85 -0
- package/dist/src/__tests__/frame-command.test.js.map +1 -0
- package/dist/src/__tests__/output.test.d.ts +0 -0
- package/dist/src/__tests__/output.test.d.ts.map +0 -0
- package/dist/src/__tests__/output.test.js +0 -0
- package/dist/src/__tests__/output.test.js.map +0 -0
- package/dist/src/__tests__/ref-cache.test.d.ts +0 -0
- package/dist/src/__tests__/ref-cache.test.d.ts.map +0 -0
- package/dist/src/__tests__/ref-cache.test.js +43 -2
- package/dist/src/__tests__/ref-cache.test.js.map +1 -1
- package/dist/src/__tests__/session-state.test.d.ts +2 -0
- package/dist/src/__tests__/session-state.test.d.ts.map +1 -0
- package/dist/src/__tests__/session-state.test.js +203 -0
- package/dist/src/__tests__/session-state.test.js.map +1 -0
- package/dist/src/__tests__/snapshot.test.d.ts +2 -0
- package/dist/src/__tests__/snapshot.test.d.ts.map +1 -0
- package/dist/src/__tests__/snapshot.test.js +262 -0
- package/dist/src/__tests__/snapshot.test.js.map +1 -0
- package/dist/src/__tests__/storage-eval.test.d.ts +2 -0
- package/dist/src/__tests__/storage-eval.test.d.ts.map +1 -0
- package/dist/src/__tests__/storage-eval.test.js +133 -0
- package/dist/src/__tests__/storage-eval.test.js.map +1 -0
- package/dist/src/__tests__/tabs.test.d.ts +2 -0
- package/dist/src/__tests__/tabs.test.d.ts.map +1 -0
- package/dist/src/__tests__/tabs.test.js +161 -0
- package/dist/src/__tests__/tabs.test.js.map +1 -0
- package/dist/src/browser/action-builder/analyzer.d.ts +0 -0
- package/dist/src/browser/action-builder/analyzer.d.ts.map +0 -0
- package/dist/src/browser/action-builder/analyzer.js +0 -0
- package/dist/src/browser/action-builder/analyzer.js.map +0 -0
- package/dist/src/browser/action-builder/types.d.ts +0 -0
- package/dist/src/browser/action-builder/types.d.ts.map +0 -0
- package/dist/src/browser/action-builder/types.js +0 -0
- package/dist/src/browser/action-builder/types.js.map +0 -0
- package/dist/src/browser/actions.d.ts +0 -0
- package/dist/src/browser/actions.d.ts.map +0 -0
- package/dist/src/browser/actions.js +0 -0
- package/dist/src/browser/actions.js.map +0 -0
- package/dist/src/browser/adapters/gemini.d.ts +0 -0
- package/dist/src/browser/adapters/gemini.d.ts.map +0 -0
- package/dist/src/browser/adapters/gemini.js +0 -0
- package/dist/src/browser/adapters/gemini.js.map +0 -0
- package/dist/src/browser/adapters/google.d.ts +0 -0
- package/dist/src/browser/adapters/google.d.ts.map +0 -0
- package/dist/src/browser/adapters/google.js +0 -0
- package/dist/src/browser/adapters/google.js.map +0 -0
- package/dist/src/browser/adapters/index.d.ts +0 -0
- package/dist/src/browser/adapters/index.d.ts.map +0 -0
- package/dist/src/browser/adapters/index.js +0 -0
- package/dist/src/browser/adapters/index.js.map +0 -0
- package/dist/src/browser/adapters/instagram.d.ts +0 -0
- package/dist/src/browser/adapters/instagram.d.ts.map +0 -0
- package/dist/src/browser/adapters/instagram.js +0 -0
- package/dist/src/browser/adapters/instagram.js.map +0 -0
- package/dist/src/browser/adapters/linkedin.d.ts +0 -0
- package/dist/src/browser/adapters/linkedin.d.ts.map +0 -0
- package/dist/src/browser/adapters/linkedin.js +0 -0
- package/dist/src/browser/adapters/linkedin.js.map +0 -0
- package/dist/src/browser/adapters/microsoft.d.ts +0 -0
- package/dist/src/browser/adapters/microsoft.d.ts.map +0 -0
- package/dist/src/browser/adapters/microsoft.js +0 -0
- package/dist/src/browser/adapters/microsoft.js.map +0 -0
- package/dist/src/browser/adapters/x.d.ts +0 -0
- package/dist/src/browser/adapters/x.d.ts.map +0 -0
- package/dist/src/browser/adapters/x.js +0 -0
- package/dist/src/browser/adapters/x.js.map +0 -0
- package/dist/src/browser/batch.d.ts +0 -0
- package/dist/src/browser/batch.d.ts.map +0 -0
- package/dist/src/browser/batch.js +0 -0
- package/dist/src/browser/batch.js.map +0 -0
- package/dist/src/browser/browser.d.ts +4 -0
- package/dist/src/browser/browser.d.ts.map +1 -1
- package/dist/src/browser/browser.js +55 -7
- package/dist/src/browser/browser.js.map +1 -1
- package/dist/src/browser/cdp.d.ts +4 -1
- package/dist/src/browser/cdp.d.ts.map +1 -1
- package/dist/src/browser/cdp.js +45 -16
- package/dist/src/browser/cdp.js.map +1 -1
- package/dist/src/browser/console-log.d.ts +0 -0
- package/dist/src/browser/console-log.d.ts.map +0 -0
- package/dist/src/browser/console-log.js +0 -0
- package/dist/src/browser/console-log.js.map +0 -0
- package/dist/src/browser/dashboard/api-types.d.ts +0 -0
- package/dist/src/browser/dashboard/api-types.d.ts.map +0 -0
- package/dist/src/browser/dashboard/api-types.js +0 -0
- package/dist/src/browser/dashboard/api-types.js.map +0 -0
- package/dist/src/browser/dashboard/server.d.ts +0 -0
- package/dist/src/browser/dashboard/server.d.ts.map +0 -0
- package/dist/src/browser/dashboard/server.js +0 -0
- package/dist/src/browser/dashboard/server.js.map +0 -0
- package/dist/src/browser/dialog.d.ts +0 -0
- package/dist/src/browser/dialog.d.ts.map +0 -0
- package/dist/src/browser/dialog.js +0 -0
- package/dist/src/browser/dialog.js.map +0 -0
- package/dist/src/browser/emulation.d.ts +0 -0
- package/dist/src/browser/emulation.d.ts.map +0 -0
- package/dist/src/browser/emulation.js +0 -0
- package/dist/src/browser/emulation.js.map +0 -0
- package/dist/src/browser/find.d.ts +0 -0
- package/dist/src/browser/find.d.ts.map +0 -0
- package/dist/src/browser/find.js +0 -0
- package/dist/src/browser/find.js.map +0 -0
- package/dist/src/browser/har.d.ts +0 -0
- package/dist/src/browser/har.d.ts.map +0 -0
- package/dist/src/browser/har.js +0 -0
- package/dist/src/browser/har.js.map +0 -0
- package/dist/src/browser/index.d.ts +0 -0
- package/dist/src/browser/index.d.ts.map +0 -0
- package/dist/src/browser/index.js +0 -0
- package/dist/src/browser/index.js.map +0 -0
- package/dist/src/browser/network.d.ts +0 -0
- package/dist/src/browser/network.d.ts.map +0 -0
- package/dist/src/browser/network.js +0 -0
- package/dist/src/browser/network.js.map +0 -0
- package/dist/src/browser/pdf.d.ts +0 -0
- package/dist/src/browser/pdf.d.ts.map +0 -0
- package/dist/src/browser/pdf.js +0 -0
- package/dist/src/browser/pdf.js.map +0 -0
- package/dist/src/browser/profiler.d.ts +0 -0
- package/dist/src/browser/profiler.d.ts.map +0 -0
- package/dist/src/browser/profiler.js +0 -0
- package/dist/src/browser/profiler.js.map +0 -0
- package/dist/src/browser/record.d.ts +0 -0
- package/dist/src/browser/record.d.ts.map +0 -0
- package/dist/src/browser/record.js +0 -0
- package/dist/src/browser/record.js.map +0 -0
- package/dist/src/browser/ref-cache.d.ts +6 -1
- package/dist/src/browser/ref-cache.d.ts.map +1 -1
- package/dist/src/browser/ref-cache.js +21 -3
- package/dist/src/browser/ref-cache.js.map +1 -1
- package/dist/src/browser/screenshot.d.ts +0 -0
- package/dist/src/browser/screenshot.d.ts.map +0 -0
- package/dist/src/browser/screenshot.js +0 -0
- package/dist/src/browser/screenshot.js.map +0 -0
- package/dist/src/browser/session.d.ts +0 -0
- package/dist/src/browser/session.d.ts.map +0 -0
- package/dist/src/browser/session.js +0 -0
- package/dist/src/browser/session.js.map +0 -0
- package/dist/src/browser/snapshot.d.ts +11 -0
- package/dist/src/browser/snapshot.d.ts.map +1 -1
- package/dist/src/browser/snapshot.js +11 -0
- package/dist/src/browser/snapshot.js.map +1 -1
- package/dist/src/browser/storage.d.ts +0 -0
- package/dist/src/browser/storage.d.ts.map +0 -0
- package/dist/src/browser/storage.js +0 -0
- package/dist/src/browser/storage.js.map +0 -0
- package/dist/src/browser/tabs.d.ts +5 -1
- package/dist/src/browser/tabs.d.ts.map +1 -1
- package/dist/src/browser/tabs.js +4 -3
- package/dist/src/browser/tabs.js.map +1 -1
- package/dist/src/browser/trace.d.ts +0 -0
- package/dist/src/browser/trace.d.ts.map +0 -0
- package/dist/src/browser/trace.js +0 -0
- package/dist/src/browser/trace.js.map +0 -0
- package/dist/src/browser/types.d.ts +4 -0
- package/dist/src/browser/types.d.ts.map +1 -1
- package/dist/src/browser/types.js +0 -0
- package/dist/src/browser/types.js.map +1 -1
- package/dist/src/browser/vitals.d.ts +0 -0
- package/dist/src/browser/vitals.d.ts.map +0 -0
- package/dist/src/browser/vitals.js +0 -0
- package/dist/src/browser/vitals.js.map +0 -0
- package/dist/src/browser/wait.d.ts +0 -0
- package/dist/src/browser/wait.d.ts.map +0 -0
- package/dist/src/browser/wait.js +0 -0
- package/dist/src/browser/wait.js.map +0 -0
- package/dist/src/cli/action.d.ts +0 -0
- package/dist/src/cli/action.d.ts.map +0 -0
- package/dist/src/cli/action.js +0 -0
- package/dist/src/cli/action.js.map +0 -0
- package/dist/src/cli/commands.d.ts +21 -0
- package/dist/src/cli/commands.d.ts.map +1 -1
- package/dist/src/cli/commands.js +123 -7
- package/dist/src/cli/commands.js.map +1 -1
- package/dist/src/cli/output.d.ts +0 -0
- package/dist/src/cli/output.d.ts.map +0 -0
- package/dist/src/cli/output.js +0 -0
- package/dist/src/cli/output.js.map +0 -0
- package/dist/src/cli/platform.d.ts +0 -0
- package/dist/src/cli/platform.d.ts.map +0 -0
- package/dist/src/cli/platform.js +0 -0
- package/dist/src/cli/platform.js.map +0 -0
- package/dist/src/cli/types.d.ts +0 -0
- package/dist/src/cli/types.d.ts.map +0 -0
- package/dist/src/cli/types.js +0 -0
- package/dist/src/cli/types.js.map +0 -0
- package/dist/src/cli.d.ts +0 -0
- package/dist/src/cli.d.ts.map +0 -0
- package/dist/src/cli.js +0 -0
- package/dist/src/cli.js.map +0 -0
- package/dist/src/index.d.ts +0 -0
- package/dist/src/index.d.ts.map +0 -0
- package/dist/src/index.js +0 -0
- package/dist/src/index.js.map +0 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -5
- package/src/__tests__/adapters.test.ts +125 -0
- package/src/__tests__/box-model.test.ts +39 -0
- package/src/__tests__/cdp-client.test.ts +375 -0
- package/src/__tests__/close-browser.test.ts +141 -0
- package/src/__tests__/console-log.test.ts +250 -0
- package/src/__tests__/find.test.ts +354 -0
- package/src/__tests__/frame-command.test.ts +98 -0
- package/src/__tests__/ref-cache.test.ts +47 -2
- package/src/__tests__/session-state.test.ts +251 -0
- package/src/__tests__/snapshot.test.ts +331 -0
- package/src/__tests__/storage-eval.test.ts +171 -0
- package/src/__tests__/tabs.test.ts +183 -0
- package/src/browser/browser.ts +59 -7
- package/src/browser/cdp.ts +52 -15
- package/src/browser/ref-cache.ts +29 -6
- package/src/browser/snapshot.ts +11 -0
- package/src/browser/tabs.ts +12 -4
- package/src/browser/types.ts +4 -0
- package/src/cli/commands.ts +119 -7
package/src/browser/tabs.ts
CHANGED
|
@@ -24,11 +24,16 @@ export async function activateTab(client: CdpClient, oldSessionId: string, targe
|
|
|
24
24
|
return result.sessionId;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
export interface FrameSwitchResult {
|
|
28
|
+
url: string | null;
|
|
29
|
+
sessionId: string | null;
|
|
30
|
+
}
|
|
31
|
+
|
|
27
32
|
export async function switchToFrame(
|
|
28
33
|
client: CdpClient,
|
|
29
34
|
sessionId: string,
|
|
30
35
|
frameSelector: string
|
|
31
|
-
): Promise<
|
|
36
|
+
): Promise<FrameSwitchResult> {
|
|
32
37
|
const { result } = await client.send<{ result: { result: { value: string | null } } }>(
|
|
33
38
|
'Runtime.evaluate',
|
|
34
39
|
{
|
|
@@ -50,7 +55,7 @@ export async function switchToFrame(
|
|
|
50
55
|
const match = frameTree.childFrames?.find(
|
|
51
56
|
(cf) => cf.frame.url === frameSrc || cf.frame.id === frameSelector
|
|
52
57
|
);
|
|
53
|
-
if (!match) return frameSrc;
|
|
58
|
+
if (!match) return { url: frameSrc, sessionId: null };
|
|
54
59
|
|
|
55
60
|
const targets = await client.send<{ targetInfos: Array<{ targetId: string; type: string; url: string }> }>(
|
|
56
61
|
'Target.getTargets', {}
|
|
@@ -59,8 +64,11 @@ export async function switchToFrame(
|
|
|
59
64
|
(t) => t.type === 'iframe' && t.url === match.frame.url
|
|
60
65
|
);
|
|
61
66
|
if (oopif) {
|
|
62
|
-
await client.send
|
|
67
|
+
const attached = await client.send<{ sessionId: string }>(
|
|
68
|
+
'Target.attachToTarget', { targetId: oopif.targetId, flatten: true }
|
|
69
|
+
);
|
|
70
|
+
return { url: frameSrc, sessionId: attached.sessionId };
|
|
63
71
|
}
|
|
64
72
|
|
|
65
|
-
return frameSrc;
|
|
73
|
+
return { url: frameSrc, sessionId: null };
|
|
66
74
|
}
|
package/src/browser/types.ts
CHANGED
|
@@ -9,6 +9,10 @@ export interface BrowserConfig {
|
|
|
9
9
|
executablePath?: string;
|
|
10
10
|
userDataDir?: string;
|
|
11
11
|
args?: string[];
|
|
12
|
+
/** Milliseconds to wait for the launched Chrome to open its CDP port
|
|
13
|
+
* before giving up. Default 10000 — raise this for environments where
|
|
14
|
+
* process spawn is consistently slower (e.g. constrained CI runners). */
|
|
15
|
+
launchTimeoutMs?: number;
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
export interface SessionState {
|
package/src/cli/commands.ts
CHANGED
|
@@ -16,11 +16,52 @@ let _sessionId = '';
|
|
|
16
16
|
let _targetId = '';
|
|
17
17
|
let _port = DEFAULT_PORT;
|
|
18
18
|
let _refs: Map<string, ElementRef> = new Map();
|
|
19
|
+
// Saved parent sessionId when inside an iframe — restored by `frame main`.
|
|
20
|
+
let _parentSessionId = '';
|
|
19
21
|
|
|
20
22
|
async function getBrowser() {
|
|
21
23
|
return import('../index.js');
|
|
22
24
|
}
|
|
23
25
|
|
|
26
|
+
// Best-effort cleanup on Ctrl-C / kill so a launched Chrome doesn't linger as
|
|
27
|
+
// an orphan process when a command is interrupted mid-flight (e.g. during a
|
|
28
|
+
// long-running wait/eval that CdpClient.send()'s own timeout hasn't tripped
|
|
29
|
+
// yet).
|
|
30
|
+
//
|
|
31
|
+
// This module is imported for EVERY `monomind` CLI invocation (commands/
|
|
32
|
+
// index.ts statically imports browse.ts, which imports this file) — not just
|
|
33
|
+
// browse commands — so the handler is only *registered* once a browser
|
|
34
|
+
// session is actually launched here (see ensureSignalCleanupHandlers(),
|
|
35
|
+
// called from the `open` action below), not at module load. Registering
|
|
36
|
+
// unconditionally at import time would call process.exit() on Ctrl-C for
|
|
37
|
+
// every unrelated monomind command (e.g. a long-running `org run` daemon),
|
|
38
|
+
// pre-empting whatever other SIGINT/SIGTERM handling that process needs.
|
|
39
|
+
const SIGNAL_EXIT_CODES: Record<'SIGINT' | 'SIGTERM', number> = { SIGINT: 130, SIGTERM: 143 };
|
|
40
|
+
let _signalHandlersRegistered = false;
|
|
41
|
+
function ensureSignalCleanupHandlers(): void {
|
|
42
|
+
if (_signalHandlersRegistered) return;
|
|
43
|
+
_signalHandlersRegistered = true;
|
|
44
|
+
for (const sig of ['SIGINT', 'SIGTERM'] as const) {
|
|
45
|
+
process.on(sig, () => {
|
|
46
|
+
void (async () => {
|
|
47
|
+
try {
|
|
48
|
+
const browser = await getBrowser();
|
|
49
|
+
if (_client) {
|
|
50
|
+
await browser.closeBrowser(_client, _port);
|
|
51
|
+
} else {
|
|
52
|
+
const pid = browser.getLaunchedPid(_port);
|
|
53
|
+
if (pid !== undefined) {
|
|
54
|
+
try { process.kill(pid, 'SIGKILL'); } catch { /* already exited */ }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
} catch {
|
|
58
|
+
// best-effort — never block process exit on cleanup failure
|
|
59
|
+
}
|
|
60
|
+
})().finally(() => process.exit(SIGNAL_EXIT_CODES[sig]));
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
24
65
|
// Each CLI invocation is a fresh process, so this module's `_port` variable
|
|
25
66
|
// is always freshly initialized to DEFAULT_PORT — a `--port 9333` passed to
|
|
26
67
|
// an earlier `open` command has no effect on this process's own default.
|
|
@@ -62,6 +103,7 @@ async function ensureConnected(port: number, targetId?: string) {
|
|
|
62
103
|
_client = conn.client;
|
|
63
104
|
_sessionId = conn.sessionId;
|
|
64
105
|
_targetId = conn.target.id;
|
|
106
|
+
_parentSessionId = '';
|
|
65
107
|
_refs = new Map();
|
|
66
108
|
await hydrateRefsFromCache(browser, _targetId, conn.target.url);
|
|
67
109
|
}
|
|
@@ -157,6 +199,7 @@ async function switchToHeaded(url: string, port: number): Promise<void> {
|
|
|
157
199
|
_client.close();
|
|
158
200
|
_client = null;
|
|
159
201
|
_sessionId = '';
|
|
202
|
+
_parentSessionId = '';
|
|
160
203
|
_targetId = '';
|
|
161
204
|
}
|
|
162
205
|
|
|
@@ -203,6 +246,7 @@ async function switchToHeaded(url: string, port: number): Promise<void> {
|
|
|
203
246
|
_client.close();
|
|
204
247
|
_client = null;
|
|
205
248
|
_sessionId = '';
|
|
249
|
+
_parentSessionId = '';
|
|
206
250
|
_targetId = '';
|
|
207
251
|
|
|
208
252
|
// Relaunch headless and restore session
|
|
@@ -277,14 +321,40 @@ const openCommand: Command = {
|
|
|
277
321
|
prevClient.close();
|
|
278
322
|
_client = null;
|
|
279
323
|
_sessionId = '';
|
|
324
|
+
_parentSessionId = '';
|
|
280
325
|
_targetId = '';
|
|
281
326
|
_refs = new Map();
|
|
282
327
|
}
|
|
283
328
|
|
|
284
329
|
_port = await browser.launchBrowser({ port, headless: !forceHeaded });
|
|
285
330
|
// Persist the active port so subsequent CLI invocations (each a fresh
|
|
286
|
-
// process) default to attaching here instead of hardcoded 9222.
|
|
287
|
-
|
|
331
|
+
// process) default to attaching here instead of hardcoded 9222. Also
|
|
332
|
+
// persist the launched PID/userDataDir so a later process's closeBrowser
|
|
333
|
+
// can still kill this Chrome even though launchedPids (browser.ts) is
|
|
334
|
+
// per-process and empty there.
|
|
335
|
+
//
|
|
336
|
+
// launchBrowser() can either LAUNCH a fresh Chrome or ATTACH to one
|
|
337
|
+
// already listening on the requested port (see its own "attach if
|
|
338
|
+
// already Chrome" comment) — it returns only a port number, with no
|
|
339
|
+
// signal telling this caller which happened. getLaunchedPid(_port) is
|
|
340
|
+
// undefined on the attach path (this process never spawned anything).
|
|
341
|
+
// Bug fixed here: unconditionally saving {pid: undefined, ...} on
|
|
342
|
+
// attach used to CLOBBER a real PID a previous `open` had already
|
|
343
|
+
// persisted for this exact port, destroying the only way a later
|
|
344
|
+
// process's closeBrowser() PID-kill fallback could ever find it.
|
|
345
|
+
const freshPid = browser.getLaunchedPid(_port);
|
|
346
|
+
const freshUserDataDir = browser.getLaunchedUserDataDir(_port);
|
|
347
|
+
if (freshPid !== undefined) {
|
|
348
|
+
await browser.saveActivePort(_port, { pid: freshPid, userDataDir: freshUserDataDir });
|
|
349
|
+
} else {
|
|
350
|
+
// Attach path: preserve whatever PID/userDataDir was already on file
|
|
351
|
+
// for this port (most likely from the process that originally
|
|
352
|
+
// launched it) instead of overwriting with undefined.
|
|
353
|
+
const existing = await browser.loadActivePortInfo();
|
|
354
|
+
const preserved = existing && existing.port === _port ? existing : undefined;
|
|
355
|
+
await browser.saveActivePort(_port, { pid: preserved?.pid, userDataDir: preserved?.userDataDir });
|
|
356
|
+
}
|
|
357
|
+
ensureSignalCleanupHandlers();
|
|
288
358
|
const conn = await browser.connectToTarget(_port);
|
|
289
359
|
_client = conn.client;
|
|
290
360
|
_sessionId = conn.sessionId;
|
|
@@ -777,7 +847,8 @@ const getCommand: Command = {
|
|
|
777
847
|
const refKey = refArg.startsWith('@') ? refArg.slice(1) : refArg;
|
|
778
848
|
const ref = _refs.get(refKey);
|
|
779
849
|
if (!ref) throw new Error(`Ref @${refKey} not found`);
|
|
780
|
-
|
|
850
|
+
const center = await browser.getElementBox(client, sessionId, ref);
|
|
851
|
+
value = deriveBoxOutput(center);
|
|
781
852
|
break;
|
|
782
853
|
}
|
|
783
854
|
case 'styles': {
|
|
@@ -1274,6 +1345,7 @@ const closeCommand: Command = {
|
|
|
1274
1345
|
client.close();
|
|
1275
1346
|
_client = null;
|
|
1276
1347
|
_sessionId = '';
|
|
1348
|
+
_parentSessionId = '';
|
|
1277
1349
|
_targetId = '';
|
|
1278
1350
|
_refs = new Map();
|
|
1279
1351
|
// Session is gone — forget the persisted port and stale refs so later
|
|
@@ -1591,8 +1663,11 @@ const tapCommand: Command = {
|
|
|
1591
1663
|
const ref = await browser.resolveRef(client, sessionId, _refs, key);
|
|
1592
1664
|
const box = await browser.getElementBox(client, sessionId, ref);
|
|
1593
1665
|
if (!box) throw new Error(`Cannot get bounds for @${key}`);
|
|
1594
|
-
|
|
1595
|
-
|
|
1666
|
+
// box.x/box.y from getElementBox() ARE already the center point (see
|
|
1667
|
+
// its own doc comment) — adding width/2 here double-offset the tap
|
|
1668
|
+
// target away from the element (issue #15).
|
|
1669
|
+
x = Math.round(box.x);
|
|
1670
|
+
y = Math.round(box.y);
|
|
1596
1671
|
} else {
|
|
1597
1672
|
const posJson = await browser.evaluateJs(client, sessionId,
|
|
1598
1673
|
`(function(){var el=document.querySelector(${JSON.stringify(arg)});if(!el)return null;var r=el.getBoundingClientRect();return JSON.stringify({x:r.left+r.width/2,y:r.top+r.height/2});})()`) as string | null;
|
|
@@ -1915,10 +1990,23 @@ const frameCommand: Command = {
|
|
|
1915
1990
|
if (!target) throw new Error('Usage: monomind browse frame <selector>|main');
|
|
1916
1991
|
|
|
1917
1992
|
if (target === 'main') {
|
|
1993
|
+
if (_parentSessionId) {
|
|
1994
|
+
// Detach from the OOPIF session (best-effort — it may already be gone)
|
|
1995
|
+
await client.send('Target.detachFromTarget', { sessionId: _sessionId }).catch(() => {});
|
|
1996
|
+
_sessionId = _parentSessionId;
|
|
1997
|
+
_parentSessionId = '';
|
|
1998
|
+
}
|
|
1918
1999
|
output.printSuccess('Switched to main frame');
|
|
1919
2000
|
} else {
|
|
1920
|
-
const
|
|
1921
|
-
|
|
2001
|
+
const frameResult = await browser.switchToFrame(client, sessionId, target);
|
|
2002
|
+
if (frameResult.sessionId) {
|
|
2003
|
+
// Save the parent session so `frame main` can restore it
|
|
2004
|
+
_parentSessionId = _sessionId;
|
|
2005
|
+
_sessionId = frameResult.sessionId;
|
|
2006
|
+
// Enable CDP domains on the iframe's session so subsequent commands work
|
|
2007
|
+
await browser.enableSessionDomains(client, _sessionId);
|
|
2008
|
+
}
|
|
2009
|
+
output.printSuccess(`Switched to frame: ${frameResult.url ?? target}`);
|
|
1922
2010
|
}
|
|
1923
2011
|
return { success: true };
|
|
1924
2012
|
},
|
|
@@ -1970,6 +2058,7 @@ const tabCommand: Command = {
|
|
|
1970
2058
|
client.close();
|
|
1971
2059
|
_client = null;
|
|
1972
2060
|
_sessionId = '';
|
|
2061
|
+
_parentSessionId = '';
|
|
1973
2062
|
_targetId = '';
|
|
1974
2063
|
_refs = new Map();
|
|
1975
2064
|
} else {
|
|
@@ -2497,8 +2586,30 @@ function tokenizeBatchCommand(input: string): string[] {
|
|
|
2497
2586
|
* only its own known --flags are consumed from the front; everything after
|
|
2498
2587
|
* them is taken verbatim as one argument, untouched by tokenization.
|
|
2499
2588
|
*
|
|
2589
|
+
/**
|
|
2590
|
+
* `get box`'s output shape: browser.getElementBox() returns the element's
|
|
2591
|
+
* CENTER point under x/y (correct for internal click-target callers), but
|
|
2592
|
+
* `get box` is a bounding-box accessor where x/y conventionally means the
|
|
2593
|
+
* top-left origin — a caller computing its own center as `box.x + width/2`
|
|
2594
|
+
* would otherwise double-offset away from the element (issue #15). Expose
|
|
2595
|
+
* both conventions, explicitly labeled, so neither is ambiguous.
|
|
2596
|
+
*
|
|
2500
2597
|
* Exported for direct unit testing — not part of the CLI's public API.
|
|
2501
2598
|
*/
|
|
2599
|
+
export function deriveBoxOutput(
|
|
2600
|
+
center: { x: number; y: number; width: number; height: number } | null
|
|
2601
|
+
): { x: number; y: number; width: number; height: number; centerX: number; centerY: number } | null {
|
|
2602
|
+
if (!center) return null;
|
|
2603
|
+
return {
|
|
2604
|
+
x: center.x - center.width / 2,
|
|
2605
|
+
y: center.y - center.height / 2,
|
|
2606
|
+
width: center.width,
|
|
2607
|
+
height: center.height,
|
|
2608
|
+
centerX: center.x,
|
|
2609
|
+
centerY: center.y,
|
|
2610
|
+
};
|
|
2611
|
+
}
|
|
2612
|
+
|
|
2502
2613
|
export function parseBatchCommandLine(cmdStr: string): { subName: string; subArgs: string[]; flags: Record<string, unknown> } {
|
|
2503
2614
|
const trimmed = cmdStr.trim();
|
|
2504
2615
|
const evalMatch = trimmed.match(/^eval\b\s*/);
|
|
@@ -2700,6 +2811,7 @@ const connectCommand: Command = {
|
|
|
2700
2811
|
prevClient.close();
|
|
2701
2812
|
_client = null;
|
|
2702
2813
|
_sessionId = '';
|
|
2814
|
+
_parentSessionId = '';
|
|
2703
2815
|
_targetId = '';
|
|
2704
2816
|
_refs = new Map();
|
|
2705
2817
|
}
|