pi-browser-use 0.11.6 → 0.11.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/dist/chrome-launcher.d.ts +4 -0
- package/dist/chrome-launcher.js +69 -27
- package/package.json +1 -1
- package/plugin.json +1 -1
|
@@ -6,6 +6,7 @@ export interface ChromeLaunchOptions {
|
|
|
6
6
|
chromeArgs?: string[];
|
|
7
7
|
executablePath?: string;
|
|
8
8
|
readyTimeoutMs?: number;
|
|
9
|
+
launchAttempts?: number;
|
|
9
10
|
signal?: AbortSignal;
|
|
10
11
|
}
|
|
11
12
|
export interface ChromeProcess {
|
|
@@ -28,6 +29,9 @@ export declare function buildChromeArgs(options: {
|
|
|
28
29
|
headless?: boolean;
|
|
29
30
|
chromeArgs?: string[];
|
|
30
31
|
}): string[];
|
|
32
|
+
export declare class DevToolsReadyTimeoutError extends Error {
|
|
33
|
+
constructor(browserUrl: string, timeoutMs: number, lastError: unknown);
|
|
34
|
+
}
|
|
31
35
|
export declare function waitForDevToolsEndpoint(port: number, options?: {
|
|
32
36
|
timeoutMs?: number;
|
|
33
37
|
fetchImpl?: typeof fetch;
|
package/dist/chrome-launcher.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execFileSync, spawn } from 'node:child_process';
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
|
+
import { once } from 'node:events';
|
|
3
4
|
import { createServer } from 'node:net';
|
|
4
5
|
import { setTimeout as delay } from 'node:timers/promises';
|
|
5
6
|
export function chromeExecutableCandidates() {
|
|
@@ -94,6 +95,21 @@ export function buildChromeArgs(options) {
|
|
|
94
95
|
args.push(...(options.chromeArgs ?? []));
|
|
95
96
|
return args;
|
|
96
97
|
}
|
|
98
|
+
export class DevToolsReadyTimeoutError extends Error {
|
|
99
|
+
constructor(browserUrl, timeoutMs, lastError) {
|
|
100
|
+
super(`Timed out waiting for Chrome DevTools on ${browserUrl} after ${timeoutMs}ms (${describeError(lastError)})`);
|
|
101
|
+
this.name = 'DevToolsReadyTimeoutError';
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function describeError(error) {
|
|
105
|
+
if (error instanceof Error) {
|
|
106
|
+
const cause = error.cause;
|
|
107
|
+
if (cause instanceof Error && cause.message)
|
|
108
|
+
return cause.message;
|
|
109
|
+
return error.message;
|
|
110
|
+
}
|
|
111
|
+
return String(error);
|
|
112
|
+
}
|
|
97
113
|
export async function waitForDevToolsEndpoint(port, options) {
|
|
98
114
|
const timeoutMs = options?.timeoutMs ?? 15_000;
|
|
99
115
|
const fetchImpl = options?.fetchImpl ?? fetch;
|
|
@@ -118,7 +134,7 @@ export async function waitForDevToolsEndpoint(port, options) {
|
|
|
118
134
|
}
|
|
119
135
|
await delay(100, undefined, { signal: options?.signal });
|
|
120
136
|
}
|
|
121
|
-
throw new
|
|
137
|
+
throw new DevToolsReadyTimeoutError(browserUrl, timeoutMs, lastError);
|
|
122
138
|
}
|
|
123
139
|
class OwnedChromeProcess {
|
|
124
140
|
port;
|
|
@@ -168,40 +184,66 @@ class OwnedChromeProcess {
|
|
|
168
184
|
}
|
|
169
185
|
}
|
|
170
186
|
}
|
|
187
|
+
async function waitReadyWatchingExit(child, port, timeoutMs, signal) {
|
|
188
|
+
const endpointReady = waitForDevToolsEndpoint(port, { timeoutMs, signal });
|
|
189
|
+
const exited = once(child, 'exit');
|
|
190
|
+
exited.catch(() => { });
|
|
191
|
+
try {
|
|
192
|
+
await Promise.race([
|
|
193
|
+
endpointReady,
|
|
194
|
+
exited.then(([code, exitSignal]) => {
|
|
195
|
+
const reason = code !== null ? `code ${code}` : `signal ${exitSignal ?? 'unknown'}`;
|
|
196
|
+
throw new Error(`Chrome exited (${reason}) before the DevTools endpoint on http://127.0.0.1:${port} opened.`);
|
|
197
|
+
}),
|
|
198
|
+
]);
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
endpointReady.catch(() => { });
|
|
202
|
+
throw error;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
171
205
|
export async function launchChrome(options) {
|
|
172
206
|
options.signal?.throwIfAborted();
|
|
173
207
|
const executable = findChromeExecutable(options.executablePath);
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
port
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
setTimeout(resolve, 50);
|
|
186
|
-
});
|
|
187
|
-
if (child.exitCode !== null) {
|
|
188
|
-
throw new Error(`Chrome exited immediately (code ${child.exitCode}).`);
|
|
189
|
-
}
|
|
190
|
-
try {
|
|
191
|
-
await waitForDevToolsEndpoint(port, {
|
|
192
|
-
timeoutMs: options.readyTimeoutMs,
|
|
193
|
-
signal: options.signal,
|
|
208
|
+
const attempts = Math.max(1, options.launchAttempts ?? 2);
|
|
209
|
+
let lastError;
|
|
210
|
+
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
211
|
+
options.signal?.throwIfAborted();
|
|
212
|
+
const port = options.port ?? (await allocateEphemeralPort());
|
|
213
|
+
const args = buildChromeArgs({
|
|
214
|
+
userDataDir: options.userDataDir,
|
|
215
|
+
profileDirectory: options.profileDirectory,
|
|
216
|
+
port,
|
|
217
|
+
headless: options.headless,
|
|
218
|
+
chromeArgs: options.chromeArgs,
|
|
194
219
|
});
|
|
195
|
-
|
|
196
|
-
|
|
220
|
+
const child = spawn(executable, args, { stdio: 'ignore', detached: false });
|
|
221
|
+
await new Promise((resolve, reject) => {
|
|
222
|
+
child.on('error', reject);
|
|
223
|
+
setTimeout(resolve, 50);
|
|
224
|
+
});
|
|
225
|
+
if (child.exitCode !== null) {
|
|
226
|
+
throw new Error(`Chrome exited immediately (code ${child.exitCode}).`);
|
|
227
|
+
}
|
|
197
228
|
try {
|
|
198
|
-
child.
|
|
229
|
+
await waitReadyWatchingExit(child, port, options.readyTimeoutMs, options.signal);
|
|
230
|
+
return new OwnedChromeProcess(child, port, `http://127.0.0.1:${port}`, options.userDataDir);
|
|
199
231
|
}
|
|
200
|
-
catch {
|
|
232
|
+
catch (error) {
|
|
233
|
+
try {
|
|
234
|
+
child.kill('SIGKILL');
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
}
|
|
238
|
+
lastError = error;
|
|
239
|
+
if (!(error instanceof DevToolsReadyTimeoutError))
|
|
240
|
+
throw error;
|
|
201
241
|
}
|
|
202
|
-
throw error;
|
|
203
242
|
}
|
|
204
|
-
|
|
243
|
+
if (lastError instanceof DevToolsReadyTimeoutError && attempts > 1) {
|
|
244
|
+
lastError.message += ` (${attempts} launch attempts)`;
|
|
245
|
+
}
|
|
246
|
+
throw lastError;
|
|
205
247
|
}
|
|
206
248
|
export function buildFrontProcessScript(pid) {
|
|
207
249
|
return [
|
package/package.json
CHANGED
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "pi-browser-use",
|
|
4
|
-
"version": "0.11.
|
|
4
|
+
"version": "0.11.7",
|
|
5
5
|
"description": "Managed persistent, fresh, and existing Chrome sessions with focus-safe browser tools and CLI-first skills.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "0xPlayerOne"
|