@mario.andreschak/mcp-browser 3.46.1 → 3.46.2
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 +52 -52
- package/dist/audioTap.js +120 -120
- package/dist/capture.js +40 -40
- package/dist/resources.js +290 -290
- package/dist/viewHtml.js +460 -460
- package/package.json +6 -1
- package/scripts/install-browser.mjs +212 -212
package/package.json
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mario.andreschak/mcp-browser",
|
|
3
|
-
"version": "3.46.
|
|
3
|
+
"version": "3.46.2",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/mario-andreschak/FLUJO.git",
|
|
7
|
+
"directory": "mcp-servers/browser"
|
|
8
|
+
},
|
|
4
9
|
"description": "FLUJO's isolated Patchright browser MCP server",
|
|
5
10
|
"type": "module",
|
|
6
11
|
"main": "dist/index.js",
|
|
@@ -1,212 +1,212 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawnSync } from 'node:child_process';
|
|
3
|
-
import { writeFileSync } from 'node:fs';
|
|
4
|
-
import { createRequire } from 'node:module';
|
|
5
|
-
import { dirname, join, resolve } from 'node:path';
|
|
6
|
-
import { pathToFileURL } from 'node:url';
|
|
7
|
-
|
|
8
|
-
const MAX_DIAGNOSTIC_CHARS = 12_000;
|
|
9
|
-
const TRUTHY = new Set(['1', 'true', 'yes', 'on']);
|
|
10
|
-
|
|
11
|
-
function browserCli() {
|
|
12
|
-
const require = createRequire(import.meta.url);
|
|
13
|
-
return join(dirname(require.resolve('patchright/package.json')), 'cli.js');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function installBrowserDependencies({ spawn = spawnSync, env = process.env } = {}) {
|
|
17
|
-
const childEnv = { ...env };
|
|
18
|
-
delete childEnv.NODE_TLS_REJECT_UNAUTHORIZED;
|
|
19
|
-
// Inherit the terminal so Patchright can request sudo and stream apt output.
|
|
20
|
-
const child = spawn(process.execPath, [browserCli(), 'install-deps', 'chromium'], {
|
|
21
|
-
env: childEnv,
|
|
22
|
-
stdio: 'inherit',
|
|
23
|
-
});
|
|
24
|
-
if (child.error) throw child.error;
|
|
25
|
-
return Number.isInteger(child.status) ? child.status : 1;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export async function verifyBrowser({ loadChromium = async () => (await import('patchright')).chromium } = {}) {
|
|
29
|
-
const chromium = await loadChromium();
|
|
30
|
-
const browser = await chromium.launch({ headless: true, channel: 'chromium', timeout: 30_000 });
|
|
31
|
-
try {
|
|
32
|
-
const page = await browser.newPage();
|
|
33
|
-
await page.setContent('<title>FLUJO browser verification</title>', { timeout: 10_000 });
|
|
34
|
-
if (await page.title() !== 'FLUJO browser verification') {
|
|
35
|
-
throw new Error('Managed Chromium could not render the verification page.');
|
|
36
|
-
}
|
|
37
|
-
} finally {
|
|
38
|
-
await browser.close();
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function sanitizeInstallOutput(input, env = process.env) {
|
|
43
|
-
let safe = String(input ?? '');
|
|
44
|
-
safe = safe.replace(/(https?:\/\/)[^/@\s]+@/gi, '$1[REDACTED]@');
|
|
45
|
-
safe = safe.replace(/(authorization\s*:\s*(?:bearer|basic)\s+)\S+/gi, '$1[REDACTED]');
|
|
46
|
-
safe = safe.replace(/(\/\/[^\s:=]+(?::\d+)?\/:_authToken=)[^\s]+/gi, '$1[REDACTED]');
|
|
47
|
-
safe = safe.replace(/([?&](?:access_token|auth|key|password|secret|token)=)[^&\s]+/gi, '$1[REDACTED]');
|
|
48
|
-
safe = safe.replace(/\b([A-Z0-9_]*(?:TOKEN|SECRET|PASSWORD|KEY))=([^\s]+)/gi, '$1=[REDACTED]');
|
|
49
|
-
|
|
50
|
-
for (const [name, value] of Object.entries(env)) {
|
|
51
|
-
if (!value || String(value).length < 4) continue;
|
|
52
|
-
if (
|
|
53
|
-
/(?:proxy|token|secret|password|key|auth|ca(?:file|certs)?)/i.test(name) ||
|
|
54
|
-
name === 'NODE_EXTRA_CA_CERTS'
|
|
55
|
-
) {
|
|
56
|
-
safe = safe.split(String(value)).join('[REDACTED]');
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return safe.length > MAX_DIAGNOSTIC_CHARS ? safe.slice(-MAX_DIAGNOSTIC_CHARS) : safe;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function classifyBrowserInstallFailure(output) {
|
|
64
|
-
const text = String(output ?? '').toLowerCase();
|
|
65
|
-
if (/self.signed|unable to verify|certificate|cert_has_expired|unknown issuer|tls|ssl/.test(text)) {
|
|
66
|
-
return {
|
|
67
|
-
category: 'TLS_TRUST',
|
|
68
|
-
remediation: 'Trust the approved corporate CA or set FLUJO_EXTRA_CA_CERTS to a readable PEM certificate file.',
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
if (/\b407\b|proxy authentication|required proxy|proxy auth/.test(text)) {
|
|
72
|
-
return {
|
|
73
|
-
category: 'PROXY_AUTH',
|
|
74
|
-
remediation: 'Check HTTPS_PROXY/HTTP_PROXY credentials and NO_PROXY, then retry the Chromium stage.',
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
if (/enotfound|eai_again|name or service not known|dns/.test(text)) {
|
|
78
|
-
return {
|
|
79
|
-
category: 'DNS',
|
|
80
|
-
remediation: 'Check DNS and the browser download host allowlist, then retry the Chromium stage.',
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
if (/etimedout|esockettimedout|timeout|timed out/.test(text)) {
|
|
84
|
-
return {
|
|
85
|
-
category: 'TIMEOUT',
|
|
86
|
-
remediation: 'Check proxy reachability or increase FLUJO_PLAYWRIGHT_DOWNLOAD_CONNECTION_TIMEOUT.',
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
if (/host system is missing dependencies|missing librar|error while loading shared libraries|install-deps/.test(text)) {
|
|
90
|
-
return {
|
|
91
|
-
category: 'OS_DEPENDENCY',
|
|
92
|
-
remediation: 'Install the operating-system browser dependencies reported above, then retry.',
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
if (/eacces|eperm|permission denied|enospc|no space left/.test(text)) {
|
|
96
|
-
return {
|
|
97
|
-
category: 'FILESYSTEM',
|
|
98
|
-
remediation: 'Check browser-cache permissions and free disk space, then retry.',
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
category: 'BROWSER_DOWNLOAD',
|
|
103
|
-
remediation: 'Check the sanitized diagnostic above and retry only this stage after correcting the cause.',
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
function writeResultFile(result, env) {
|
|
108
|
-
const resultPath = env.FLUJO_INSTALL_RESULT_FILE;
|
|
109
|
-
if (!resultPath) return;
|
|
110
|
-
try {
|
|
111
|
-
writeFileSync(resultPath, JSON.stringify(result, null, 2), { encoding: 'utf8' });
|
|
112
|
-
} catch (error) {
|
|
113
|
-
process.stderr.write(
|
|
114
|
-
'[FLUJO installer] Could not write the browser-stage result file: ' +
|
|
115
|
-
sanitizeInstallOutput(error?.message, env) +
|
|
116
|
-
'\n',
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function runBrowserInstall({
|
|
122
|
-
env = process.env,
|
|
123
|
-
spawn = spawnSync,
|
|
124
|
-
stderr = process.stderr,
|
|
125
|
-
} = {}) {
|
|
126
|
-
if (TRUTHY.has(String(env.FLUJO_SKIP_PATCHRIGHT_DOWNLOAD ?? '').toLowerCase())) {
|
|
127
|
-
stderr.write('[FLUJO installer] Managed Chromium download deferred to the explicit patchright-chromium stage.\n');
|
|
128
|
-
const result = { ok: true, stage: 'patchright-chromium', skipped: true, exitCode: 0 };
|
|
129
|
-
writeResultFile(result, env);
|
|
130
|
-
return result;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
let child;
|
|
134
|
-
try {
|
|
135
|
-
const require = createRequire(import.meta.url);
|
|
136
|
-
const packageJson = require.resolve('patchright/package.json');
|
|
137
|
-
const cli = join(dirname(packageJson), 'cli.js');
|
|
138
|
-
const childEnv = { ...env };
|
|
139
|
-
delete childEnv.NODE_TLS_REJECT_UNAUTHORIZED;
|
|
140
|
-
child = spawn(process.execPath, [cli, 'install', 'chromium', '--no-progress'], {
|
|
141
|
-
cwd: resolve(dirname(packageJson)),
|
|
142
|
-
env: childEnv,
|
|
143
|
-
encoding: 'utf8',
|
|
144
|
-
maxBuffer: 4 * 1024 * 1024,
|
|
145
|
-
windowsHide: false,
|
|
146
|
-
});
|
|
147
|
-
} catch (error) {
|
|
148
|
-
child = { status: 1, stdout: '', stderr: '', error };
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const combined = sanitizeInstallOutput(
|
|
152
|
-
[child.stdout, child.stderr, child.error?.message].filter(Boolean).join('\n'),
|
|
153
|
-
env,
|
|
154
|
-
);
|
|
155
|
-
if (combined) stderr.write(combined.trimEnd() + '\n');
|
|
156
|
-
|
|
157
|
-
const exitCode = Number.isInteger(child.status) ? child.status : 1;
|
|
158
|
-
if (exitCode === 0) {
|
|
159
|
-
const result = { ok: true, stage: 'patchright-chromium', skipped: false, exitCode };
|
|
160
|
-
writeResultFile(result, env);
|
|
161
|
-
return result;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const failure = classifyBrowserInstallFailure(combined);
|
|
165
|
-
const result = {
|
|
166
|
-
ok: false,
|
|
167
|
-
stage: 'patchright-chromium',
|
|
168
|
-
code: 'BROWSER_UNAVAILABLE',
|
|
169
|
-
retryable: true,
|
|
170
|
-
category: failure.category,
|
|
171
|
-
remediation: failure.remediation,
|
|
172
|
-
exitCode,
|
|
173
|
-
};
|
|
174
|
-
stderr.write(
|
|
175
|
-
'[FLUJO installer] Install managed Chromium failed (' +
|
|
176
|
-
failure.category +
|
|
177
|
-
', exit ' +
|
|
178
|
-
exitCode +
|
|
179
|
-
'). ' +
|
|
180
|
-
failure.remediation +
|
|
181
|
-
'\n',
|
|
182
|
-
);
|
|
183
|
-
stderr.write(
|
|
184
|
-
'[FLUJO installer] Retry from the FLUJO directory with: node mcp-servers/browser/scripts/install-browser.mjs\n',
|
|
185
|
-
);
|
|
186
|
-
writeResultFile(result, env);
|
|
187
|
-
return result;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
async function main() {
|
|
191
|
-
try {
|
|
192
|
-
if (process.argv[2] === '--install-deps') {
|
|
193
|
-
process.exitCode = installBrowserDependencies();
|
|
194
|
-
} else if (process.argv[2] === '--verify') {
|
|
195
|
-
await verifyBrowser();
|
|
196
|
-
process.stderr.write('[FLUJO installer] Managed Chromium launch and rendering verified.\n');
|
|
197
|
-
} else {
|
|
198
|
-
const result = runBrowserInstall();
|
|
199
|
-
process.exitCode = result.exitCode;
|
|
200
|
-
}
|
|
201
|
-
} catch (error) {
|
|
202
|
-
process.stderr.write(sanitizeInstallOutput(error?.message) + '\n');
|
|
203
|
-
if (process.platform === 'linux') {
|
|
204
|
-
process.stderr.write('[FLUJO installer] Check the system browser dependencies. On Ubuntu/Debian, retry as root (using sudo when needed): node mcp-servers/browser/scripts/install-browser.mjs --install-deps\n');
|
|
205
|
-
}
|
|
206
|
-
process.exitCode = 1;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (process.argv[1] && pathToFileURL(resolve(process.argv[1])).href === import.meta.url) {
|
|
211
|
-
await main();
|
|
212
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from 'node:child_process';
|
|
3
|
+
import { writeFileSync } from 'node:fs';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import { dirname, join, resolve } from 'node:path';
|
|
6
|
+
import { pathToFileURL } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const MAX_DIAGNOSTIC_CHARS = 12_000;
|
|
9
|
+
const TRUTHY = new Set(['1', 'true', 'yes', 'on']);
|
|
10
|
+
|
|
11
|
+
function browserCli() {
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
return join(dirname(require.resolve('patchright/package.json')), 'cli.js');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function installBrowserDependencies({ spawn = spawnSync, env = process.env } = {}) {
|
|
17
|
+
const childEnv = { ...env };
|
|
18
|
+
delete childEnv.NODE_TLS_REJECT_UNAUTHORIZED;
|
|
19
|
+
// Inherit the terminal so Patchright can request sudo and stream apt output.
|
|
20
|
+
const child = spawn(process.execPath, [browserCli(), 'install-deps', 'chromium'], {
|
|
21
|
+
env: childEnv,
|
|
22
|
+
stdio: 'inherit',
|
|
23
|
+
});
|
|
24
|
+
if (child.error) throw child.error;
|
|
25
|
+
return Number.isInteger(child.status) ? child.status : 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function verifyBrowser({ loadChromium = async () => (await import('patchright')).chromium } = {}) {
|
|
29
|
+
const chromium = await loadChromium();
|
|
30
|
+
const browser = await chromium.launch({ headless: true, channel: 'chromium', timeout: 30_000 });
|
|
31
|
+
try {
|
|
32
|
+
const page = await browser.newPage();
|
|
33
|
+
await page.setContent('<title>FLUJO browser verification</title>', { timeout: 10_000 });
|
|
34
|
+
if (await page.title() !== 'FLUJO browser verification') {
|
|
35
|
+
throw new Error('Managed Chromium could not render the verification page.');
|
|
36
|
+
}
|
|
37
|
+
} finally {
|
|
38
|
+
await browser.close();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function sanitizeInstallOutput(input, env = process.env) {
|
|
43
|
+
let safe = String(input ?? '');
|
|
44
|
+
safe = safe.replace(/(https?:\/\/)[^/@\s]+@/gi, '$1[REDACTED]@');
|
|
45
|
+
safe = safe.replace(/(authorization\s*:\s*(?:bearer|basic)\s+)\S+/gi, '$1[REDACTED]');
|
|
46
|
+
safe = safe.replace(/(\/\/[^\s:=]+(?::\d+)?\/:_authToken=)[^\s]+/gi, '$1[REDACTED]');
|
|
47
|
+
safe = safe.replace(/([?&](?:access_token|auth|key|password|secret|token)=)[^&\s]+/gi, '$1[REDACTED]');
|
|
48
|
+
safe = safe.replace(/\b([A-Z0-9_]*(?:TOKEN|SECRET|PASSWORD|KEY))=([^\s]+)/gi, '$1=[REDACTED]');
|
|
49
|
+
|
|
50
|
+
for (const [name, value] of Object.entries(env)) {
|
|
51
|
+
if (!value || String(value).length < 4) continue;
|
|
52
|
+
if (
|
|
53
|
+
/(?:proxy|token|secret|password|key|auth|ca(?:file|certs)?)/i.test(name) ||
|
|
54
|
+
name === 'NODE_EXTRA_CA_CERTS'
|
|
55
|
+
) {
|
|
56
|
+
safe = safe.split(String(value)).join('[REDACTED]');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return safe.length > MAX_DIAGNOSTIC_CHARS ? safe.slice(-MAX_DIAGNOSTIC_CHARS) : safe;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function classifyBrowserInstallFailure(output) {
|
|
64
|
+
const text = String(output ?? '').toLowerCase();
|
|
65
|
+
if (/self.signed|unable to verify|certificate|cert_has_expired|unknown issuer|tls|ssl/.test(text)) {
|
|
66
|
+
return {
|
|
67
|
+
category: 'TLS_TRUST',
|
|
68
|
+
remediation: 'Trust the approved corporate CA or set FLUJO_EXTRA_CA_CERTS to a readable PEM certificate file.',
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (/\b407\b|proxy authentication|required proxy|proxy auth/.test(text)) {
|
|
72
|
+
return {
|
|
73
|
+
category: 'PROXY_AUTH',
|
|
74
|
+
remediation: 'Check HTTPS_PROXY/HTTP_PROXY credentials and NO_PROXY, then retry the Chromium stage.',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
if (/enotfound|eai_again|name or service not known|dns/.test(text)) {
|
|
78
|
+
return {
|
|
79
|
+
category: 'DNS',
|
|
80
|
+
remediation: 'Check DNS and the browser download host allowlist, then retry the Chromium stage.',
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
if (/etimedout|esockettimedout|timeout|timed out/.test(text)) {
|
|
84
|
+
return {
|
|
85
|
+
category: 'TIMEOUT',
|
|
86
|
+
remediation: 'Check proxy reachability or increase FLUJO_PLAYWRIGHT_DOWNLOAD_CONNECTION_TIMEOUT.',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (/host system is missing dependencies|missing librar|error while loading shared libraries|install-deps/.test(text)) {
|
|
90
|
+
return {
|
|
91
|
+
category: 'OS_DEPENDENCY',
|
|
92
|
+
remediation: 'Install the operating-system browser dependencies reported above, then retry.',
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (/eacces|eperm|permission denied|enospc|no space left/.test(text)) {
|
|
96
|
+
return {
|
|
97
|
+
category: 'FILESYSTEM',
|
|
98
|
+
remediation: 'Check browser-cache permissions and free disk space, then retry.',
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
category: 'BROWSER_DOWNLOAD',
|
|
103
|
+
remediation: 'Check the sanitized diagnostic above and retry only this stage after correcting the cause.',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function writeResultFile(result, env) {
|
|
108
|
+
const resultPath = env.FLUJO_INSTALL_RESULT_FILE;
|
|
109
|
+
if (!resultPath) return;
|
|
110
|
+
try {
|
|
111
|
+
writeFileSync(resultPath, JSON.stringify(result, null, 2), { encoding: 'utf8' });
|
|
112
|
+
} catch (error) {
|
|
113
|
+
process.stderr.write(
|
|
114
|
+
'[FLUJO installer] Could not write the browser-stage result file: ' +
|
|
115
|
+
sanitizeInstallOutput(error?.message, env) +
|
|
116
|
+
'\n',
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function runBrowserInstall({
|
|
122
|
+
env = process.env,
|
|
123
|
+
spawn = spawnSync,
|
|
124
|
+
stderr = process.stderr,
|
|
125
|
+
} = {}) {
|
|
126
|
+
if (TRUTHY.has(String(env.FLUJO_SKIP_PATCHRIGHT_DOWNLOAD ?? '').toLowerCase())) {
|
|
127
|
+
stderr.write('[FLUJO installer] Managed Chromium download deferred to the explicit patchright-chromium stage.\n');
|
|
128
|
+
const result = { ok: true, stage: 'patchright-chromium', skipped: true, exitCode: 0 };
|
|
129
|
+
writeResultFile(result, env);
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let child;
|
|
134
|
+
try {
|
|
135
|
+
const require = createRequire(import.meta.url);
|
|
136
|
+
const packageJson = require.resolve('patchright/package.json');
|
|
137
|
+
const cli = join(dirname(packageJson), 'cli.js');
|
|
138
|
+
const childEnv = { ...env };
|
|
139
|
+
delete childEnv.NODE_TLS_REJECT_UNAUTHORIZED;
|
|
140
|
+
child = spawn(process.execPath, [cli, 'install', 'chromium', '--no-progress'], {
|
|
141
|
+
cwd: resolve(dirname(packageJson)),
|
|
142
|
+
env: childEnv,
|
|
143
|
+
encoding: 'utf8',
|
|
144
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
145
|
+
windowsHide: false,
|
|
146
|
+
});
|
|
147
|
+
} catch (error) {
|
|
148
|
+
child = { status: 1, stdout: '', stderr: '', error };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const combined = sanitizeInstallOutput(
|
|
152
|
+
[child.stdout, child.stderr, child.error?.message].filter(Boolean).join('\n'),
|
|
153
|
+
env,
|
|
154
|
+
);
|
|
155
|
+
if (combined) stderr.write(combined.trimEnd() + '\n');
|
|
156
|
+
|
|
157
|
+
const exitCode = Number.isInteger(child.status) ? child.status : 1;
|
|
158
|
+
if (exitCode === 0) {
|
|
159
|
+
const result = { ok: true, stage: 'patchright-chromium', skipped: false, exitCode };
|
|
160
|
+
writeResultFile(result, env);
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const failure = classifyBrowserInstallFailure(combined);
|
|
165
|
+
const result = {
|
|
166
|
+
ok: false,
|
|
167
|
+
stage: 'patchright-chromium',
|
|
168
|
+
code: 'BROWSER_UNAVAILABLE',
|
|
169
|
+
retryable: true,
|
|
170
|
+
category: failure.category,
|
|
171
|
+
remediation: failure.remediation,
|
|
172
|
+
exitCode,
|
|
173
|
+
};
|
|
174
|
+
stderr.write(
|
|
175
|
+
'[FLUJO installer] Install managed Chromium failed (' +
|
|
176
|
+
failure.category +
|
|
177
|
+
', exit ' +
|
|
178
|
+
exitCode +
|
|
179
|
+
'). ' +
|
|
180
|
+
failure.remediation +
|
|
181
|
+
'\n',
|
|
182
|
+
);
|
|
183
|
+
stderr.write(
|
|
184
|
+
'[FLUJO installer] Retry from the FLUJO directory with: node mcp-servers/browser/scripts/install-browser.mjs\n',
|
|
185
|
+
);
|
|
186
|
+
writeResultFile(result, env);
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async function main() {
|
|
191
|
+
try {
|
|
192
|
+
if (process.argv[2] === '--install-deps') {
|
|
193
|
+
process.exitCode = installBrowserDependencies();
|
|
194
|
+
} else if (process.argv[2] === '--verify') {
|
|
195
|
+
await verifyBrowser();
|
|
196
|
+
process.stderr.write('[FLUJO installer] Managed Chromium launch and rendering verified.\n');
|
|
197
|
+
} else {
|
|
198
|
+
const result = runBrowserInstall();
|
|
199
|
+
process.exitCode = result.exitCode;
|
|
200
|
+
}
|
|
201
|
+
} catch (error) {
|
|
202
|
+
process.stderr.write(sanitizeInstallOutput(error?.message) + '\n');
|
|
203
|
+
if (process.platform === 'linux') {
|
|
204
|
+
process.stderr.write('[FLUJO installer] Check the system browser dependencies. On Ubuntu/Debian, retry as root (using sudo when needed): node mcp-servers/browser/scripts/install-browser.mjs --install-deps\n');
|
|
205
|
+
}
|
|
206
|
+
process.exitCode = 1;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (process.argv[1] && pathToFileURL(resolve(process.argv[1])).href === import.meta.url) {
|
|
211
|
+
await main();
|
|
212
|
+
}
|