@everydaydevopsio/pilot 0.5.0 → 0.6.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 +64 -0
- package/CLAUDE.md +9 -9
- package/README.md +108 -53
- package/dist/browser/browser-manager.d.ts +60 -0
- package/dist/browser/browser-manager.d.ts.map +1 -0
- package/dist/browser/browser-manager.js +348 -0
- package/dist/browser/browser-manager.js.map +1 -0
- package/dist/browser/chrome-launcher.d.ts +30 -0
- package/dist/browser/chrome-launcher.d.ts.map +1 -0
- package/dist/browser/chrome-launcher.js +217 -0
- package/dist/browser/chrome-launcher.js.map +1 -0
- package/dist/browser/connection.d.ts +23 -0
- package/dist/browser/connection.d.ts.map +1 -0
- package/dist/browser/connection.js +53 -0
- package/dist/browser/connection.js.map +1 -0
- package/dist/browser/events.d.ts +9 -0
- package/dist/browser/events.d.ts.map +1 -0
- package/dist/browser/events.js +99 -0
- package/dist/browser/events.js.map +1 -0
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +4 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/inspect/element-ref.d.ts +23 -0
- package/dist/browser/inspect/element-ref.d.ts.map +1 -0
- package/dist/browser/inspect/element-ref.js +52 -0
- package/dist/browser/inspect/element-ref.js.map +1 -0
- package/dist/browser/inspect/snapshot.d.ts +11 -0
- package/dist/browser/inspect/snapshot.d.ts.map +1 -0
- package/dist/browser/inspect/snapshot.js +282 -0
- package/dist/browser/inspect/snapshot.js.map +1 -0
- package/dist/browser/inspect/styles.d.ts +45 -0
- package/dist/browser/inspect/styles.d.ts.map +1 -0
- package/dist/browser/inspect/styles.js +190 -0
- package/dist/browser/inspect/styles.js.map +1 -0
- package/dist/browser/inspect/types.d.ts +35 -0
- package/dist/browser/inspect/types.d.ts.map +1 -0
- package/dist/browser/inspect/types.js +2 -0
- package/dist/browser/inspect/types.js.map +1 -0
- package/dist/browser/interaction/dialogs.d.ts +18 -0
- package/dist/browser/interaction/dialogs.d.ts.map +1 -0
- package/dist/browser/interaction/dialogs.js +35 -0
- package/dist/browser/interaction/dialogs.js.map +1 -0
- package/dist/browser/interaction/downloads.d.ts +23 -0
- package/dist/browser/interaction/downloads.d.ts.map +1 -0
- package/dist/browser/interaction/downloads.js +87 -0
- package/dist/browser/interaction/downloads.js.map +1 -0
- package/dist/browser/interaction/events.d.ts +17 -0
- package/dist/browser/interaction/events.d.ts.map +1 -0
- package/dist/browser/interaction/events.js +66 -0
- package/dist/browser/interaction/events.js.map +1 -0
- package/dist/browser/interaction/ref-resolver.d.ts +18 -0
- package/dist/browser/interaction/ref-resolver.d.ts.map +1 -0
- package/dist/browser/interaction/ref-resolver.js +32 -0
- package/dist/browser/interaction/ref-resolver.js.map +1 -0
- package/dist/browser/interaction/uploads.d.ts +4 -0
- package/dist/browser/interaction/uploads.d.ts.map +1 -0
- package/dist/browser/interaction/uploads.js +43 -0
- package/dist/browser/interaction/uploads.js.map +1 -0
- package/dist/browser/network/network-buffer.d.ts +19 -0
- package/dist/browser/network/network-buffer.d.ts.map +1 -0
- package/dist/browser/network/network-buffer.js +118 -0
- package/dist/browser/network/network-buffer.js.map +1 -0
- package/dist/browser/network/network-monitor.d.ts +8 -0
- package/dist/browser/network/network-monitor.d.ts.map +1 -0
- package/dist/browser/network/network-monitor.js +85 -0
- package/dist/browser/network/network-monitor.js.map +1 -0
- package/dist/browser/network/redaction.d.ts +3 -0
- package/dist/browser/network/redaction.d.ts.map +1 -0
- package/dist/browser/network/redaction.js +36 -0
- package/dist/browser/network/redaction.js.map +1 -0
- package/dist/browser/network/types.d.ts +45 -0
- package/dist/browser/network/types.d.ts.map +1 -0
- package/dist/browser/network/types.js +2 -0
- package/dist/browser/network/types.js.map +1 -0
- package/dist/browser/performance/analyze.d.ts +5 -0
- package/dist/browser/performance/analyze.d.ts.map +1 -0
- package/dist/browser/performance/analyze.js +230 -0
- package/dist/browser/performance/analyze.js.map +1 -0
- package/dist/browser/performance/trace.d.ts +10 -0
- package/dist/browser/performance/trace.d.ts.map +1 -0
- package/dist/browser/performance/trace.js +38 -0
- package/dist/browser/performance/trace.js.map +1 -0
- package/dist/browser/performance/types.d.ts +31 -0
- package/dist/browser/performance/types.d.ts.map +1 -0
- package/dist/browser/performance/types.js +2 -0
- package/dist/browser/performance/types.js.map +1 -0
- package/dist/browser/security/origins.d.ts +18 -0
- package/dist/browser/security/origins.d.ts.map +1 -0
- package/dist/browser/security/origins.js +84 -0
- package/dist/browser/security/origins.js.map +1 -0
- package/dist/browser/tabs.d.ts +15 -0
- package/dist/browser/tabs.d.ts.map +1 -0
- package/dist/browser/tabs.js +71 -0
- package/dist/browser/tabs.js.map +1 -0
- package/dist/browser/types.d.ts +31 -0
- package/dist/browser/types.d.ts.map +1 -0
- package/dist/browser/types.js +2 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/browser.d.ts +2 -99
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +3 -653
- package/dist/browser.js.map +1 -1
- package/dist/commands/check.d.ts +17 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +38 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/click.d.ts +3 -1
- package/dist/commands/click.d.ts.map +1 -1
- package/dist/commands/click.js +16 -4
- package/dist/commands/click.js.map +1 -1
- package/dist/commands/connect.d.ts +14 -0
- package/dist/commands/connect.d.ts.map +1 -0
- package/dist/commands/connect.js +19 -0
- package/dist/commands/connect.js.map +1 -0
- package/dist/commands/dialog.d.ts +19 -0
- package/dist/commands/dialog.d.ts.map +1 -0
- package/dist/commands/dialog.js +51 -0
- package/dist/commands/dialog.js.map +1 -0
- package/dist/commands/downloads.d.ts +30 -0
- package/dist/commands/downloads.d.ts.map +1 -0
- package/dist/commands/downloads.js +66 -0
- package/dist/commands/downloads.js.map +1 -0
- package/dist/commands/fill.d.ts +16 -0
- package/dist/commands/fill.d.ts.map +1 -0
- package/dist/commands/fill.js +15 -0
- package/dist/commands/fill.js.map +1 -0
- package/dist/commands/find.d.ts +14 -0
- package/dist/commands/find.d.ts.map +1 -0
- package/dist/commands/find.js +26 -0
- package/dist/commands/find.js.map +1 -0
- package/dist/commands/hover.d.ts +13 -0
- package/dist/commands/hover.d.ts.map +1 -0
- package/dist/commands/hover.js +24 -0
- package/dist/commands/hover.js.map +1 -0
- package/dist/commands/navigate.d.ts.map +1 -1
- package/dist/commands/navigate.js +13 -0
- package/dist/commands/navigate.js.map +1 -1
- package/dist/commands/network.d.ts +33 -0
- package/dist/commands/network.d.ts.map +1 -0
- package/dist/commands/network.js +84 -0
- package/dist/commands/network.js.map +1 -0
- package/dist/commands/performance.d.ts +12 -0
- package/dist/commands/performance.d.ts.map +1 -0
- package/dist/commands/performance.js +26 -0
- package/dist/commands/performance.js.map +1 -0
- package/dist/commands/press_key.d.ts +10 -0
- package/dist/commands/press_key.d.ts.map +1 -0
- package/dist/commands/press_key.js +103 -0
- package/dist/commands/press_key.js.map +1 -0
- package/dist/commands/scroll.d.ts +21 -0
- package/dist/commands/scroll.d.ts.map +1 -0
- package/dist/commands/scroll.js +54 -0
- package/dist/commands/scroll.js.map +1 -0
- package/dist/commands/select.d.ts +18 -0
- package/dist/commands/select.d.ts.map +1 -0
- package/dist/commands/select.js +53 -0
- package/dist/commands/select.js.map +1 -0
- package/dist/commands/snapshot.d.ts +9 -0
- package/dist/commands/snapshot.d.ts.map +1 -0
- package/dist/commands/snapshot.js +7 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/dist/commands/styles.d.ts +13 -0
- package/dist/commands/styles.d.ts.map +1 -0
- package/dist/commands/styles.js +7 -0
- package/dist/commands/styles.js.map +1 -0
- package/dist/commands/type.d.ts +3 -1
- package/dist/commands/type.d.ts.map +1 -1
- package/dist/commands/type.js +11 -2
- package/dist/commands/type.js.map +1 -1
- package/dist/commands/upload.d.ts +12 -0
- package/dist/commands/upload.d.ts.map +1 -0
- package/dist/commands/upload.js +13 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/mcp/console-buffer.d.ts +9 -0
- package/dist/mcp/console-buffer.d.ts.map +1 -1
- package/dist/mcp/console-buffer.js.map +1 -1
- package/dist/mcp/server.d.ts +10 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +63 -2
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/browser.d.ts.map +1 -1
- package/dist/mcp/tools/browser.js +99 -8
- package/dist/mcp/tools/browser.js.map +1 -1
- package/dist/mcp/tools/connect.d.ts +5 -0
- package/dist/mcp/tools/connect.d.ts.map +1 -0
- package/dist/mcp/tools/connect.js +48 -0
- package/dist/mcp/tools/connect.js.map +1 -0
- package/dist/mcp/tools/files.d.ts +4 -0
- package/dist/mcp/tools/files.d.ts.map +1 -0
- package/dist/mcp/tools/files.js +85 -0
- package/dist/mcp/tools/files.js.map +1 -0
- package/dist/mcp/tools/interaction.d.ts +4 -0
- package/dist/mcp/tools/interaction.d.ts.map +1 -0
- package/dist/mcp/tools/interaction.js +176 -0
- package/dist/mcp/tools/interaction.js.map +1 -0
- package/dist/mcp/tools/names.d.ts +1 -1
- package/dist/mcp/tools/names.d.ts.map +1 -1
- package/dist/mcp/tools/names.js +19 -1
- package/dist/mcp/tools/names.js.map +1 -1
- package/dist/mcp/tools/network.d.ts +4 -0
- package/dist/mcp/tools/network.d.ts.map +1 -0
- package/dist/mcp/tools/network.js +68 -0
- package/dist/mcp/tools/network.js.map +1 -0
- package/dist/mcp/tools/performance.d.ts +4 -0
- package/dist/mcp/tools/performance.d.ts.map +1 -0
- package/dist/mcp/tools/performance.js +26 -0
- package/dist/mcp/tools/performance.js.map +1 -0
- package/dist/mcp/tools/runtime.d.ts +4 -0
- package/dist/mcp/tools/runtime.d.ts.map +1 -0
- package/dist/mcp/tools/runtime.js +128 -0
- package/dist/mcp/tools/runtime.js.map +1 -0
- package/dist/mcp/tools/snapshot.d.ts +4 -0
- package/dist/mcp/tools/snapshot.d.ts.map +1 -0
- package/dist/mcp/tools/snapshot.js +42 -0
- package/dist/mcp/tools/snapshot.js.map +1 -0
- package/dist/mcp/tools/styles.d.ts +4 -0
- package/dist/mcp/tools/styles.d.ts.map +1 -0
- package/dist/mcp/tools/styles.js +27 -0
- package/dist/mcp/tools/styles.js.map +1 -0
- package/dist/util/config.d.ts.map +1 -1
- package/dist/util/config.js +3 -2
- package/dist/util/config.js.map +1 -1
- package/package.json +7 -3
- package/src/browser/browser-manager.ts +457 -0
- package/src/browser/chrome-launcher.ts +271 -0
- package/src/browser/connection.ts +84 -0
- package/src/browser/events.ts +121 -0
- package/src/browser/index.ts +20 -0
- package/src/browser/inspect/element-ref.ts +68 -0
- package/src/browser/inspect/snapshot.ts +348 -0
- package/src/browser/inspect/styles.ts +258 -0
- package/src/browser/inspect/types.ts +37 -0
- package/src/browser/interaction/dialogs.ts +54 -0
- package/src/browser/interaction/downloads.ts +116 -0
- package/src/browser/interaction/events.ts +79 -0
- package/src/browser/interaction/ref-resolver.ts +53 -0
- package/src/browser/interaction/uploads.ts +60 -0
- package/src/browser/network/network-buffer.ts +133 -0
- package/src/browser/network/network-monitor.ts +107 -0
- package/src/browser/network/redaction.ts +42 -0
- package/src/browser/network/types.ts +47 -0
- package/src/browser/performance/analyze.ts +298 -0
- package/src/browser/performance/trace.ts +60 -0
- package/src/browser/performance/types.ts +34 -0
- package/src/browser/security/origins.ts +102 -0
- package/src/browser/tabs.ts +110 -0
- package/src/browser/types.ts +31 -0
- package/src/browser.ts +22 -798
- package/src/commands/check.ts +59 -0
- package/src/commands/click.ts +18 -4
- package/src/commands/connect.ts +40 -0
- package/src/commands/dialog.ts +79 -0
- package/src/commands/downloads.ts +111 -0
- package/src/commands/fill.ts +34 -0
- package/src/commands/find.ts +52 -0
- package/src/commands/hover.ts +42 -0
- package/src/commands/navigate.ts +20 -0
- package/src/commands/network.ts +141 -0
- package/src/commands/performance.ts +51 -0
- package/src/commands/press_key.ts +134 -0
- package/src/commands/scroll.ts +79 -0
- package/src/commands/select.ts +78 -0
- package/src/commands/snapshot.ts +18 -0
- package/src/commands/styles.ts +24 -0
- package/src/commands/type.ts +12 -2
- package/src/commands/upload.ts +36 -0
- package/src/mcp/console-buffer.ts +10 -0
- package/src/mcp/server.ts +74 -2
- package/src/mcp/tools/browser.ts +113 -7
- package/src/mcp/tools/connect.ts +62 -0
- package/src/mcp/tools/files.ts +120 -0
- package/src/mcp/tools/interaction.ts +232 -0
- package/src/mcp/tools/names.ts +19 -1
- package/src/mcp/tools/network.ts +86 -0
- package/src/mcp/tools/performance.ts +40 -0
- package/src/mcp/tools/runtime.ts +164 -0
- package/src/mcp/tools/snapshot.ts +64 -0
- package/src/mcp/tools/styles.ts +41 -0
- package/src/util/config.ts +3 -2
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import { mkdirSync } from 'fs';
|
|
2
|
+
import { getLogger } from '../util/logger.js';
|
|
3
|
+
import { resolveViewport } from '../viewport.js';
|
|
4
|
+
import { findChromeExecutable, findFreePort, isProfileLocked, launchChrome, resolveUserDataDir, waitForChromeReady, cleanupLockFiles } from './chrome-launcher.js';
|
|
5
|
+
import { connectToChrome, enableDomains, getConnectionInfo } from './connection.js';
|
|
6
|
+
import { attachEventListeners } from './events.js';
|
|
7
|
+
import { listTabs as listTabsImpl, createTab as createTabImpl, closeTab as closeTabImpl, switchTab as switchTabImpl } from './tabs.js';
|
|
8
|
+
export class BrowserManager {
|
|
9
|
+
config;
|
|
10
|
+
client = null;
|
|
11
|
+
targetId = null;
|
|
12
|
+
currentUrl = null;
|
|
13
|
+
retryTimer = null;
|
|
14
|
+
retryMs;
|
|
15
|
+
destroyed = false;
|
|
16
|
+
intentionalClose = false;
|
|
17
|
+
eventCallback = null;
|
|
18
|
+
pendingNetworkRequests = new Set();
|
|
19
|
+
networkIdleTimer = null;
|
|
20
|
+
networkIdleResolvers = [];
|
|
21
|
+
chromeProcess = null;
|
|
22
|
+
launchedCdpPort = null;
|
|
23
|
+
viewportConfig = null;
|
|
24
|
+
launchedUserDataDir = null;
|
|
25
|
+
external = false;
|
|
26
|
+
externalHost = null;
|
|
27
|
+
externalPort = null;
|
|
28
|
+
constructor(config) {
|
|
29
|
+
this.config = config;
|
|
30
|
+
this.retryMs = config.cdpRetryMs;
|
|
31
|
+
}
|
|
32
|
+
setEventCallback(cb) {
|
|
33
|
+
this.eventCallback = cb;
|
|
34
|
+
}
|
|
35
|
+
emit(event, data) {
|
|
36
|
+
this.eventCallback?.(event, data);
|
|
37
|
+
}
|
|
38
|
+
getState() {
|
|
39
|
+
return {
|
|
40
|
+
client: this.client,
|
|
41
|
+
targetId: this.targetId,
|
|
42
|
+
url: this.currentUrl,
|
|
43
|
+
connected: this.client !== null
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
getClient() {
|
|
47
|
+
return this.client;
|
|
48
|
+
}
|
|
49
|
+
isConnected() {
|
|
50
|
+
return this.client !== null;
|
|
51
|
+
}
|
|
52
|
+
isLaunched() {
|
|
53
|
+
return this.chromeProcess !== null;
|
|
54
|
+
}
|
|
55
|
+
isExternalChrome() {
|
|
56
|
+
return this.external;
|
|
57
|
+
}
|
|
58
|
+
getViewportConfig() {
|
|
59
|
+
return this.viewportConfig;
|
|
60
|
+
}
|
|
61
|
+
setViewportConfig(config) {
|
|
62
|
+
this.viewportConfig = config;
|
|
63
|
+
}
|
|
64
|
+
static findChromeExecutable(override) {
|
|
65
|
+
return findChromeExecutable(override);
|
|
66
|
+
}
|
|
67
|
+
static async findFreePort() {
|
|
68
|
+
return findFreePort();
|
|
69
|
+
}
|
|
70
|
+
getConnectionInfo() {
|
|
71
|
+
return getConnectionInfo(this.config, this.launchedCdpPort);
|
|
72
|
+
}
|
|
73
|
+
makeEventListenerOpts() {
|
|
74
|
+
return {
|
|
75
|
+
emit: (event, data) => this.emit(event, data),
|
|
76
|
+
onDisconnect: () => {
|
|
77
|
+
if (this.intentionalClose) {
|
|
78
|
+
this.intentionalClose = false;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const logger = getLogger();
|
|
82
|
+
logger.warn('Chrome disconnected');
|
|
83
|
+
this.client = null;
|
|
84
|
+
this.targetId = null;
|
|
85
|
+
this.emit('browser_disconnected', {
|
|
86
|
+
reason: 'chrome_disconnected'
|
|
87
|
+
});
|
|
88
|
+
this.scheduleReconnect();
|
|
89
|
+
},
|
|
90
|
+
pendingNetworkRequests: this.pendingNetworkRequests,
|
|
91
|
+
checkNetworkIdle: () => this.checkNetworkIdle(),
|
|
92
|
+
onFrameNavigated: (url) => {
|
|
93
|
+
this.currentUrl = url;
|
|
94
|
+
this.emit('page_navigated', {
|
|
95
|
+
url,
|
|
96
|
+
timestamp: Date.now()
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
async launch(opts = {}) {
|
|
102
|
+
if (this.chromeProcess) {
|
|
103
|
+
throw new Error('Chrome is already launched');
|
|
104
|
+
}
|
|
105
|
+
if (this.destroyed) {
|
|
106
|
+
throw new Error('BrowserManager has been destroyed; create a new instance');
|
|
107
|
+
}
|
|
108
|
+
const port = await findFreePort();
|
|
109
|
+
const chromePath = findChromeExecutable(opts.chromePath);
|
|
110
|
+
const profileName = opts.profileName ?? this.config.profileName;
|
|
111
|
+
const userDataDir = resolveUserDataDir(profileName);
|
|
112
|
+
if (isProfileLocked(userDataDir)) {
|
|
113
|
+
throw new Error(`Profile "${profileName}" is already in use by another browser instance.`);
|
|
114
|
+
}
|
|
115
|
+
mkdirSync(userDataDir, { recursive: true });
|
|
116
|
+
const viewportPreset = opts.viewport ?? this.config.viewport;
|
|
117
|
+
this.viewportConfig = resolveViewport({
|
|
118
|
+
preset: viewportPreset,
|
|
119
|
+
width: opts.viewportWidth,
|
|
120
|
+
height: opts.viewportHeight,
|
|
121
|
+
deviceScaleFactor: opts.deviceScaleFactor,
|
|
122
|
+
responsive: opts.responsive ?? this.config.responsive
|
|
123
|
+
});
|
|
124
|
+
const headless = opts.headless ?? this.config.headless;
|
|
125
|
+
this.chromeProcess = launchChrome({
|
|
126
|
+
chromePath,
|
|
127
|
+
port,
|
|
128
|
+
userDataDir,
|
|
129
|
+
headless,
|
|
130
|
+
windowWidth: this.viewportConfig.width,
|
|
131
|
+
windowHeight: this.viewportConfig.height
|
|
132
|
+
});
|
|
133
|
+
this.launchedCdpPort = port;
|
|
134
|
+
this.launchedUserDataDir = userDataDir;
|
|
135
|
+
const stderrChunks = [];
|
|
136
|
+
this.chromeProcess.stderr?.on('data', (data) => {
|
|
137
|
+
stderrChunks.push(data.toString());
|
|
138
|
+
});
|
|
139
|
+
this.chromeProcess.on('exit', (code, signal) => {
|
|
140
|
+
const logger = getLogger();
|
|
141
|
+
const stderr = stderrChunks.join('').trim();
|
|
142
|
+
const stderrFiltered = stderr
|
|
143
|
+
.split('\n')
|
|
144
|
+
.filter((l) => !l.includes('dbus/bus.cc'))
|
|
145
|
+
.join('\n')
|
|
146
|
+
.trim();
|
|
147
|
+
logger.warn({
|
|
148
|
+
code,
|
|
149
|
+
signal,
|
|
150
|
+
...(stderrFiltered && { stderr: stderrFiltered.slice(0, 1000) }),
|
|
151
|
+
...(stderr && !stderrFiltered && { stderrRaw: stderr.slice(0, 500) })
|
|
152
|
+
}, 'Chrome process exited');
|
|
153
|
+
this.chromeProcess = null;
|
|
154
|
+
this.launchedCdpPort = null;
|
|
155
|
+
this.cleanupUserDataDir();
|
|
156
|
+
});
|
|
157
|
+
await waitForChromeReady(port);
|
|
158
|
+
await this.connect();
|
|
159
|
+
return { headless, viewport: viewportPreset };
|
|
160
|
+
}
|
|
161
|
+
async connect() {
|
|
162
|
+
if (this.destroyed)
|
|
163
|
+
return;
|
|
164
|
+
const logger = getLogger();
|
|
165
|
+
try {
|
|
166
|
+
const connInfo = this.getConnectionInfo();
|
|
167
|
+
const { client, targetId, url } = await connectToChrome(connInfo);
|
|
168
|
+
this.client = client;
|
|
169
|
+
this.targetId = targetId;
|
|
170
|
+
this.currentUrl = url;
|
|
171
|
+
this.retryMs = this.config.cdpRetryMs;
|
|
172
|
+
await enableDomains(client, this.viewportConfig);
|
|
173
|
+
attachEventListeners(client, this.makeEventListenerOpts());
|
|
174
|
+
logger.info({ targetId: this.targetId, url: this.currentUrl }, 'Connected to Chrome');
|
|
175
|
+
this.emit('browser_connected', {
|
|
176
|
+
targetId: this.targetId,
|
|
177
|
+
url: this.currentUrl
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
catch (err) {
|
|
181
|
+
logger.warn({ err, retryMs: this.retryMs }, 'Failed to connect to Chrome, retrying...');
|
|
182
|
+
this.scheduleReconnect();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async connectExisting(opts) {
|
|
186
|
+
if (this.chromeProcess) {
|
|
187
|
+
throw new Error('Chrome was launched by Pilot. Use browser_stop first, then browser_connect.');
|
|
188
|
+
}
|
|
189
|
+
if (this.destroyed) {
|
|
190
|
+
throw new Error('BrowserManager has been destroyed; create a new instance');
|
|
191
|
+
}
|
|
192
|
+
const logger = getLogger();
|
|
193
|
+
const host = opts.host ?? '127.0.0.1';
|
|
194
|
+
const port = opts.port ?? 9222;
|
|
195
|
+
this.external = true;
|
|
196
|
+
this.externalHost = host;
|
|
197
|
+
this.externalPort = port;
|
|
198
|
+
this.launchedCdpPort = port;
|
|
199
|
+
// Override connection info for external Chrome
|
|
200
|
+
const connInfo = { host, port };
|
|
201
|
+
try {
|
|
202
|
+
const { client, targetId, url } = await connectToChrome(connInfo);
|
|
203
|
+
this.client = client;
|
|
204
|
+
this.targetId = targetId;
|
|
205
|
+
this.currentUrl = url;
|
|
206
|
+
this.retryMs = this.config.cdpRetryMs;
|
|
207
|
+
await enableDomains(client, this.viewportConfig);
|
|
208
|
+
attachEventListeners(client, this.makeEventListenerOpts());
|
|
209
|
+
logger.info({ host, port, targetId, url }, 'Connected to existing Chrome');
|
|
210
|
+
this.emit('browser_connected', { targetId, url });
|
|
211
|
+
const tabs = await this.listTabs();
|
|
212
|
+
return { tabs };
|
|
213
|
+
}
|
|
214
|
+
catch (cause) {
|
|
215
|
+
this.external = false;
|
|
216
|
+
this.externalHost = null;
|
|
217
|
+
this.externalPort = null;
|
|
218
|
+
this.launchedCdpPort = null;
|
|
219
|
+
throw new Error(`Could not connect to Chrome at ${host}:${port}. ` +
|
|
220
|
+
`Start Chrome with --remote-debugging-port=${port} or use browser_start to launch a new instance.`, { cause });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
checkNetworkIdle() {
|
|
224
|
+
if (this.pendingNetworkRequests.size === 0) {
|
|
225
|
+
if (this.networkIdleTimer)
|
|
226
|
+
clearTimeout(this.networkIdleTimer);
|
|
227
|
+
this.networkIdleTimer = setTimeout(() => {
|
|
228
|
+
const resolvers = this.networkIdleResolvers.splice(0);
|
|
229
|
+
resolvers.forEach((r) => r());
|
|
230
|
+
}, 500);
|
|
231
|
+
this.networkIdleTimer.unref();
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
waitForNetworkIdle(timeoutMs = 10000) {
|
|
235
|
+
return new Promise((resolve, reject) => {
|
|
236
|
+
if (this.pendingNetworkRequests.size === 0) {
|
|
237
|
+
resolve();
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const timer = setTimeout(() => {
|
|
241
|
+
const idx = this.networkIdleResolvers.indexOf(resolve);
|
|
242
|
+
if (idx !== -1)
|
|
243
|
+
this.networkIdleResolvers.splice(idx, 1);
|
|
244
|
+
reject(new Error('timeout waiting for network idle'));
|
|
245
|
+
}, timeoutMs);
|
|
246
|
+
this.networkIdleResolvers.push(() => {
|
|
247
|
+
clearTimeout(timer);
|
|
248
|
+
resolve();
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
async listTabs() {
|
|
253
|
+
return listTabsImpl(this.getConnectionInfo(), this.targetId);
|
|
254
|
+
}
|
|
255
|
+
async createTab(url) {
|
|
256
|
+
return createTabImpl(this.getConnectionInfo(), url);
|
|
257
|
+
}
|
|
258
|
+
async closeTab(targetId) {
|
|
259
|
+
return closeTabImpl(this.getConnectionInfo(), targetId, this.targetId);
|
|
260
|
+
}
|
|
261
|
+
async switchTab(targetId) {
|
|
262
|
+
if (targetId === this.targetId)
|
|
263
|
+
return;
|
|
264
|
+
// Clear any pending reconnect from a prior disconnect
|
|
265
|
+
if (this.retryTimer) {
|
|
266
|
+
clearTimeout(this.retryTimer);
|
|
267
|
+
this.retryTimer = null;
|
|
268
|
+
}
|
|
269
|
+
this.intentionalClose = true;
|
|
270
|
+
const result = await switchTabImpl(this.getConnectionInfo(), targetId, this.targetId, this.client, this.viewportConfig, this.makeEventListenerOpts());
|
|
271
|
+
this.client = result.client;
|
|
272
|
+
this.targetId = result.targetId;
|
|
273
|
+
this.currentUrl = result.url;
|
|
274
|
+
this.retryMs = this.config.cdpRetryMs;
|
|
275
|
+
}
|
|
276
|
+
scheduleReconnect() {
|
|
277
|
+
if (this.destroyed)
|
|
278
|
+
return;
|
|
279
|
+
if (this.retryTimer)
|
|
280
|
+
return;
|
|
281
|
+
this.retryTimer = setTimeout(() => {
|
|
282
|
+
this.retryTimer = null;
|
|
283
|
+
this.retryMs = Math.min(this.retryMs * 2, this.config.cdpMaxRetryMs);
|
|
284
|
+
void this.connect();
|
|
285
|
+
}, this.retryMs);
|
|
286
|
+
this.retryTimer.unref();
|
|
287
|
+
}
|
|
288
|
+
cleanupUserDataDir() {
|
|
289
|
+
if (this.launchedUserDataDir) {
|
|
290
|
+
cleanupLockFiles(this.launchedUserDataDir);
|
|
291
|
+
}
|
|
292
|
+
this.launchedUserDataDir = null;
|
|
293
|
+
}
|
|
294
|
+
async destroy() {
|
|
295
|
+
this.destroyed = true;
|
|
296
|
+
if (this.retryTimer) {
|
|
297
|
+
clearTimeout(this.retryTimer);
|
|
298
|
+
this.retryTimer = null;
|
|
299
|
+
}
|
|
300
|
+
if (this.networkIdleTimer) {
|
|
301
|
+
clearTimeout(this.networkIdleTimer);
|
|
302
|
+
}
|
|
303
|
+
if (this.client) {
|
|
304
|
+
await this.client.close();
|
|
305
|
+
this.client = null;
|
|
306
|
+
}
|
|
307
|
+
// External Chrome: just disconnect, don't kill the process
|
|
308
|
+
if (this.external) {
|
|
309
|
+
this.external = false;
|
|
310
|
+
this.externalHost = null;
|
|
311
|
+
this.externalPort = null;
|
|
312
|
+
this.launchedCdpPort = null;
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
if (this.chromeProcess) {
|
|
316
|
+
const proc = this.chromeProcess;
|
|
317
|
+
this.chromeProcess = null;
|
|
318
|
+
this.launchedCdpPort = null;
|
|
319
|
+
try {
|
|
320
|
+
proc.kill();
|
|
321
|
+
}
|
|
322
|
+
catch {
|
|
323
|
+
// process may have already exited
|
|
324
|
+
}
|
|
325
|
+
await new Promise((resolve) => {
|
|
326
|
+
if (proc.exitCode !== null) {
|
|
327
|
+
resolve();
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const timer = setTimeout(() => {
|
|
331
|
+
try {
|
|
332
|
+
proc.kill('SIGKILL');
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
// process may have already exited
|
|
336
|
+
}
|
|
337
|
+
resolve();
|
|
338
|
+
}, 5000);
|
|
339
|
+
proc.once('exit', () => {
|
|
340
|
+
clearTimeout(timer);
|
|
341
|
+
resolve();
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
this.cleanupUserDataDir();
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=browser-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-manager.js","sourceRoot":"","sources":["../../src/browser/browser-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ChildProcess } from 'child_process';
|
|
2
|
+
import type { SandboxDecision } from './types.js';
|
|
3
|
+
export declare const PROFILE_NAME_RE: RegExp;
|
|
4
|
+
export declare function sandboxDecision(): SandboxDecision;
|
|
5
|
+
export declare function shouldDisableSandbox(): boolean;
|
|
6
|
+
export declare function resolveUserDataDir(profileName: string): string;
|
|
7
|
+
export declare function extractLockPid(lockPath: string): {
|
|
8
|
+
pid: number;
|
|
9
|
+
lockHost: string;
|
|
10
|
+
} | null;
|
|
11
|
+
export declare function isProcessAlive(pid: number): boolean;
|
|
12
|
+
export declare function isProfileLocked(userDataDir: string): boolean;
|
|
13
|
+
export declare function findChromeExecutable(override?: string): string;
|
|
14
|
+
export declare function findFreePort(): Promise<number>;
|
|
15
|
+
export declare function waitForChromeReady(port: number, timeoutMs?: number): Promise<void>;
|
|
16
|
+
export interface ChromeLaunchResult {
|
|
17
|
+
process: ChildProcess;
|
|
18
|
+
port: number;
|
|
19
|
+
userDataDir: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function launchChrome(opts: {
|
|
22
|
+
chromePath: string;
|
|
23
|
+
port: number;
|
|
24
|
+
userDataDir: string;
|
|
25
|
+
headless: boolean;
|
|
26
|
+
windowWidth: number;
|
|
27
|
+
windowHeight: number;
|
|
28
|
+
}): ChildProcess;
|
|
29
|
+
export declare function cleanupLockFiles(userDataDir: string): void;
|
|
30
|
+
//# sourceMappingURL=chrome-launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chrome-launcher.d.ts","sourceRoot":"","sources":["../../src/browser/chrome-launcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAOzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,eAAe,QAAgC,CAAC;AAE7D,wBAAgB,eAAe,IAAI,eAAe,CAejD;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAS9D;AAeD,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,GACf;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAc1C;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CASnD;AAkBD,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CA8B5D;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAiC9D;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CASpD;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,SAAS,SAAQ,GAChB,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,YAAY,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,YAAY,CAkDf;AAED,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAQ1D"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { existsSync, lstatSync, readlinkSync, unlinkSync } from 'fs';
|
|
3
|
+
import * as net from 'net';
|
|
4
|
+
import { homedir, hostname } from 'os';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import CDP from 'chrome-remote-interface';
|
|
7
|
+
import { getLogger } from '../util/logger.js';
|
|
8
|
+
export const PROFILE_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
|
|
9
|
+
export function sandboxDecision() {
|
|
10
|
+
const envOverride = process.env.PILOT_CHROME_NO_SANDBOX;
|
|
11
|
+
if (envOverride !== undefined) {
|
|
12
|
+
const truthy = envOverride === 'true' || envOverride === '1';
|
|
13
|
+
return truthy
|
|
14
|
+
? { disable: true, reason: 'env_override' }
|
|
15
|
+
: { disable: false };
|
|
16
|
+
}
|
|
17
|
+
if (process.platform !== 'linux' && process.platform !== 'win32') {
|
|
18
|
+
return { disable: false };
|
|
19
|
+
}
|
|
20
|
+
if (process.getuid?.() === 0) {
|
|
21
|
+
return { disable: true, reason: 'root_user' };
|
|
22
|
+
}
|
|
23
|
+
return { disable: false };
|
|
24
|
+
}
|
|
25
|
+
export function shouldDisableSandbox() {
|
|
26
|
+
return sandboxDecision().disable;
|
|
27
|
+
}
|
|
28
|
+
export function resolveUserDataDir(profileName) {
|
|
29
|
+
if (!PROFILE_NAME_RE.test(profileName)) {
|
|
30
|
+
throw new Error(`Invalid profile name "${profileName}". Use only letters, digits, hyphens, and underscores.`);
|
|
31
|
+
}
|
|
32
|
+
const xdgData = process.env.XDG_DATA_HOME || join(homedir(), '.local', 'share');
|
|
33
|
+
return join(xdgData, 'pilot', profileName);
|
|
34
|
+
}
|
|
35
|
+
function fileOrSymlinkExists(filePath) {
|
|
36
|
+
try {
|
|
37
|
+
lstatSync(filePath);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
const code = err?.code;
|
|
42
|
+
if (code === 'ENOENT' || code === 'ENOTDIR') {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export function extractLockPid(lockPath) {
|
|
49
|
+
try {
|
|
50
|
+
const stat = lstatSync(lockPath);
|
|
51
|
+
if (!stat.isSymbolicLink())
|
|
52
|
+
return null;
|
|
53
|
+
const target = readlinkSync(lockPath);
|
|
54
|
+
const lastDash = target.lastIndexOf('-');
|
|
55
|
+
if (lastDash === -1)
|
|
56
|
+
return null;
|
|
57
|
+
const lockHost = target.slice(0, lastDash);
|
|
58
|
+
const pid = parseInt(target.slice(lastDash + 1), 10);
|
|
59
|
+
if (isNaN(pid) || pid <= 0)
|
|
60
|
+
return null;
|
|
61
|
+
return { pid, lockHost };
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function isProcessAlive(pid) {
|
|
68
|
+
if (pid <= 0)
|
|
69
|
+
return false;
|
|
70
|
+
try {
|
|
71
|
+
process.kill(pid, 0);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const code = err?.code;
|
|
76
|
+
return code !== 'ESRCH';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function removeStaleLocks(userDataDir) {
|
|
80
|
+
for (const lockName of ['SingletonLock', 'lockfile']) {
|
|
81
|
+
try {
|
|
82
|
+
unlinkSync(join(userDataDir, lockName));
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
const code = err?.code;
|
|
86
|
+
if (code !== 'ENOENT')
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const logger = getLogger();
|
|
91
|
+
logger.warn({ userDataDir }, 'Cleaned up stale Chrome lock files from a previous crash');
|
|
92
|
+
}
|
|
93
|
+
export function isProfileLocked(userDataDir) {
|
|
94
|
+
const singletonPath = join(userDataDir, 'SingletonLock');
|
|
95
|
+
const lockfilePath = join(userDataDir, 'lockfile');
|
|
96
|
+
const hasSingleton = fileOrSymlinkExists(singletonPath);
|
|
97
|
+
const hasLockfile = existsSync(lockfilePath);
|
|
98
|
+
if (!hasSingleton && !hasLockfile)
|
|
99
|
+
return false;
|
|
100
|
+
const lockInfo = hasSingleton ? extractLockPid(singletonPath) : null;
|
|
101
|
+
if (!lockInfo) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
const currentHost = hostname();
|
|
105
|
+
if (lockInfo.lockHost !== currentHost) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
if (isProcessAlive(lockInfo.pid)) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
removeStaleLocks(userDataDir);
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export function findChromeExecutable(override) {
|
|
120
|
+
if (override)
|
|
121
|
+
return override;
|
|
122
|
+
const env = process.env.PILOT_CHROME_PATH;
|
|
123
|
+
if (env)
|
|
124
|
+
return env;
|
|
125
|
+
const platform = process.platform;
|
|
126
|
+
const candidates = platform === 'darwin'
|
|
127
|
+
? [
|
|
128
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
129
|
+
'/Applications/Chromium.app/Contents/MacOS/Chromium'
|
|
130
|
+
]
|
|
131
|
+
: platform === 'linux'
|
|
132
|
+
? [
|
|
133
|
+
'/usr/bin/google-chrome-stable',
|
|
134
|
+
'/usr/bin/google-chrome',
|
|
135
|
+
'/usr/bin/chromium-browser',
|
|
136
|
+
'/usr/bin/chromium',
|
|
137
|
+
'/snap/bin/chromium'
|
|
138
|
+
]
|
|
139
|
+
: platform === 'win32'
|
|
140
|
+
? [
|
|
141
|
+
'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
|
|
142
|
+
'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe'
|
|
143
|
+
]
|
|
144
|
+
: [];
|
|
145
|
+
for (const p of candidates) {
|
|
146
|
+
if (existsSync(p))
|
|
147
|
+
return p;
|
|
148
|
+
}
|
|
149
|
+
throw new Error(`Chrome not found on ${platform}. Install Google Chrome or set PILOT_CHROME_PATH.`);
|
|
150
|
+
}
|
|
151
|
+
export async function findFreePort() {
|
|
152
|
+
return new Promise((resolve, reject) => {
|
|
153
|
+
const server = net.createServer();
|
|
154
|
+
server.listen(0, '127.0.0.1', () => {
|
|
155
|
+
const { port } = server.address();
|
|
156
|
+
server.close(() => resolve(port));
|
|
157
|
+
});
|
|
158
|
+
server.on('error', reject);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
export async function waitForChromeReady(port, timeoutMs = 10000) {
|
|
162
|
+
const deadline = Date.now() + timeoutMs;
|
|
163
|
+
while (Date.now() < deadline) {
|
|
164
|
+
try {
|
|
165
|
+
await CDP.List({ host: '127.0.0.1', port });
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
throw new Error(`Chrome did not become ready on port ${port} within ${timeoutMs}ms`);
|
|
173
|
+
}
|
|
174
|
+
export function launchChrome(opts) {
|
|
175
|
+
const logger = getLogger();
|
|
176
|
+
const args = [
|
|
177
|
+
`--remote-debugging-port=${opts.port}`,
|
|
178
|
+
`--user-data-dir=${opts.userDataDir}`,
|
|
179
|
+
`--window-size=${opts.windowWidth},${opts.windowHeight}`,
|
|
180
|
+
'--no-first-run',
|
|
181
|
+
'--no-default-browser-check',
|
|
182
|
+
'--disable-default-apps',
|
|
183
|
+
'--disable-extensions'
|
|
184
|
+
];
|
|
185
|
+
if (opts.headless) {
|
|
186
|
+
args.push('--headless', '--disable-gpu');
|
|
187
|
+
}
|
|
188
|
+
if (process.platform === 'linux') {
|
|
189
|
+
args.push('--disable-dev-shm-usage', '--disable-software-rasterizer', '--disable-breakpad', '--password-store=basic', '--use-mock-keychain');
|
|
190
|
+
}
|
|
191
|
+
const sandbox = sandboxDecision();
|
|
192
|
+
if (sandbox.disable) {
|
|
193
|
+
args.push('--no-sandbox');
|
|
194
|
+
logger.warn({ reason: sandbox.reason }, 'Chrome will run with --no-sandbox. The renderer sandbox is disabled; any page the agent visits runs with the same privileges as this process. Set PILOT_CHROME_NO_SANDBOX=false to override, or run as a non-root user to keep the sandbox enabled.');
|
|
195
|
+
}
|
|
196
|
+
logger.info({
|
|
197
|
+
chromePath: opts.chromePath,
|
|
198
|
+
port: opts.port,
|
|
199
|
+
headless: opts.headless,
|
|
200
|
+
sandbox: sandbox.disable ? 'disabled' : 'enabled'
|
|
201
|
+
}, 'Launching Chrome');
|
|
202
|
+
return spawn(opts.chromePath, args, {
|
|
203
|
+
stdio: ['ignore', 'ignore', 'pipe'],
|
|
204
|
+
detached: false
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
export function cleanupLockFiles(userDataDir) {
|
|
208
|
+
for (const lockName of ['SingletonLock', 'lockfile']) {
|
|
209
|
+
try {
|
|
210
|
+
unlinkSync(join(userDataDir, lockName));
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
// lock file may not exist — that's fine
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=chrome-launcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chrome-launcher.js","sourceRoot":"","sources":["../../src/browser/chrome-launcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Client } from 'chrome-remote-interface';
|
|
2
|
+
import type { Config } from '../util/config.js';
|
|
3
|
+
import { type ViewportConfig } from '../viewport.js';
|
|
4
|
+
export interface ConnectionInfo {
|
|
5
|
+
host: string;
|
|
6
|
+
port: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function connectToChrome(opts: {
|
|
9
|
+
host: string;
|
|
10
|
+
port: number;
|
|
11
|
+
}): Promise<{
|
|
12
|
+
client: Client;
|
|
13
|
+
targetId: string;
|
|
14
|
+
url: string;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function enableDomains(client: Client, viewportConfig: ViewportConfig | null): Promise<void>;
|
|
17
|
+
export declare function getConnectionInfo(config: Config, launchedCdpPort: number | null): ConnectionInfo;
|
|
18
|
+
export declare function scheduleReconnect(config: Config, state: {
|
|
19
|
+
destroyed: boolean;
|
|
20
|
+
retryTimer: ReturnType<typeof setTimeout> | null;
|
|
21
|
+
retryMs: number;
|
|
22
|
+
}, reconnectFn: () => void): ReturnType<typeof setTimeout> | null;
|
|
23
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/browser/connection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,KAAK,cAAc,EAAiB,MAAM,gBAAgB,CAAC;AAEpE,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAmB7D;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,cAAc,GAAG,IAAI,GACpC,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,GAAG,IAAI,GAC7B,cAAc,CAKhB;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;IACL,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC;IACjD,OAAO,EAAE,MAAM,CAAC;CACjB,EACD,WAAW,EAAE,MAAM,IAAI,GACtB,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,CActC"}
|