pi-browser-use 0.9.6 → 0.10.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/README.md +3 -0
- package/dist/artifacts.d.ts +1 -1
- package/dist/artifacts.js +2 -2
- package/dist/chrome-launcher.d.ts +3 -0
- package/dist/chrome-launcher.js +38 -5
- package/dist/client.js +11 -2
- package/dist/config.d.ts +2 -2
- package/dist/config.js +12 -8
- package/dist/existing-flow.js +4 -2
- package/dist/index.d.ts +8 -35
- package/dist/index.js +17 -904
- package/dist/mcp-server.d.ts +47 -0
- package/dist/mcp-server.js +218 -0
- package/dist/persistent-backend.d.ts +1 -1
- package/dist/persistent-backend.js +10 -5
- package/dist/profile-lock.js +1 -1
- package/dist/runtime.d.ts +45 -0
- package/dist/runtime.js +1019 -0
- package/dist/setup-flow.d.ts +7 -1
- package/dist/setup-flow.js +17 -1
- package/dist/tab-bridge.js +5 -1
- package/docs/agent-plugins.md +131 -0
- package/mcp.json +14 -0
- package/package.json +9 -4
- package/plugin.json +12 -0
- package/skills/auth-bootstrap/SKILL.md +39 -36
- package/skills/browser-policy/SKILL.md +17 -13
- package/skills/gmail-auth/SKILL.md +6 -3
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# pi-browser-use
|
|
2
2
|
|
|
3
|
+
Native Pi extension **and Agent Plugins 1.0 / standalone MCP server**, sharing the same
|
|
4
|
+
curated browser runtime. See [portable installation and configuration](docs/agent-plugins.md).
|
|
5
|
+
|
|
3
6
|
Opinionated browser-use for the [Pi coding agent](https://pi.dev), powered by [`chrome-devtools-mcp`](https://github.com/ChromeDevTools/chrome-devtools-mcp) — not Playwright.
|
|
4
7
|
|
|
5
8
|
## Why this exists
|
package/dist/artifacts.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type ArtifactKind = 'screenshot' | 'html';
|
|
2
2
|
export declare function defaultArtifactDir(): string;
|
|
3
3
|
/** Resolve the destination file: explicit path wins, otherwise a timestamped file in the default dir. */
|
|
4
|
-
export declare function resolveArtifactTarget(kind: ArtifactKind, path?: unknown): string;
|
|
4
|
+
export declare function resolveArtifactTarget(kind: ArtifactKind, path?: unknown, directory?: string): string;
|
|
5
5
|
/** Pick the first image payload out of MCP content, if any. */
|
|
6
6
|
export declare function pickImageData(content: unknown): {
|
|
7
7
|
data: string;
|
package/dist/artifacts.js
CHANGED
|
@@ -4,10 +4,10 @@ export function defaultArtifactDir() {
|
|
|
4
4
|
return join(homedir(), '.pi', 'browser-artifacts');
|
|
5
5
|
}
|
|
6
6
|
/** Resolve the destination file: explicit path wins, otherwise a timestamped file in the default dir. */
|
|
7
|
-
export function resolveArtifactTarget(kind, path) {
|
|
7
|
+
export function resolveArtifactTarget(kind, path, directory = defaultArtifactDir()) {
|
|
8
8
|
if (typeof path === 'string' && path.length > 0)
|
|
9
9
|
return path;
|
|
10
|
-
return join(
|
|
10
|
+
return join(directory, `page-${Date.now()}.${kind === 'html' ? 'html' : 'png'}`);
|
|
11
11
|
}
|
|
12
12
|
/** Pick the first image payload out of MCP content, if any. */
|
|
13
13
|
export function pickImageData(content) {
|
|
@@ -28,6 +28,7 @@ export interface ChromeLaunchOptions {
|
|
|
28
28
|
executablePath?: string;
|
|
29
29
|
/** How long to wait for the DevTools endpoint. Default 15s. */
|
|
30
30
|
readyTimeoutMs?: number;
|
|
31
|
+
signal?: AbortSignal;
|
|
31
32
|
}
|
|
32
33
|
export interface ChromeProcess {
|
|
33
34
|
readonly pid: number | undefined;
|
|
@@ -68,6 +69,7 @@ export declare function buildChromeArgs(options: {
|
|
|
68
69
|
export declare function waitForDevToolsEndpoint(port: number, options?: {
|
|
69
70
|
timeoutMs?: number;
|
|
70
71
|
fetchImpl?: typeof fetch;
|
|
72
|
+
signal?: AbortSignal;
|
|
71
73
|
}): Promise<{
|
|
72
74
|
browserUrl: string;
|
|
73
75
|
webSocketDebuggerUrl: string;
|
|
@@ -102,5 +104,6 @@ export declare function launchSetupBrowser(options: {
|
|
|
102
104
|
profileDirectory?: string;
|
|
103
105
|
executablePath?: string;
|
|
104
106
|
chromeArgs?: string[];
|
|
107
|
+
signal?: AbortSignal;
|
|
105
108
|
}): Promise<number | null>;
|
|
106
109
|
//# sourceMappingURL=chrome-launcher.d.ts.map
|
package/dist/chrome-launcher.js
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
import { execFileSync, spawn } from 'node:child_process';
|
|
20
20
|
import { existsSync } from 'node:fs';
|
|
21
21
|
import { createServer } from 'node:net';
|
|
22
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
22
23
|
/** Chrome/Chromium executable candidates by platform (stable first). */
|
|
23
24
|
export function chromeExecutableCandidates() {
|
|
24
25
|
if (process.platform === 'darwin') {
|
|
@@ -131,8 +132,11 @@ export async function waitForDevToolsEndpoint(port, options) {
|
|
|
131
132
|
const deadline = Date.now() + timeoutMs;
|
|
132
133
|
let lastError;
|
|
133
134
|
while (Date.now() < deadline) {
|
|
135
|
+
options?.signal?.throwIfAborted();
|
|
134
136
|
try {
|
|
135
|
-
const
|
|
137
|
+
const timeout = AbortSignal.timeout(Math.max(1, Math.min(1000, deadline - Date.now())));
|
|
138
|
+
const signal = options?.signal ? AbortSignal.any([options.signal, timeout]) : timeout;
|
|
139
|
+
const response = await fetchImpl(`${browserUrl}/json/version`, { signal });
|
|
136
140
|
if (response.ok) {
|
|
137
141
|
const info = (await response.json());
|
|
138
142
|
return { browserUrl, webSocketDebuggerUrl: info.webSocketDebuggerUrl ?? '' };
|
|
@@ -140,9 +144,10 @@ export async function waitForDevToolsEndpoint(port, options) {
|
|
|
140
144
|
lastError = new Error(`DevTools endpoint answered ${response.status}`);
|
|
141
145
|
}
|
|
142
146
|
catch (error) {
|
|
147
|
+
options?.signal?.throwIfAborted();
|
|
143
148
|
lastError = error;
|
|
144
149
|
}
|
|
145
|
-
await
|
|
150
|
+
await delay(100, undefined, { signal: options?.signal });
|
|
146
151
|
}
|
|
147
152
|
throw new Error(`Timed out waiting for Chrome DevTools on ${browserUrl} (${lastError instanceof Error ? lastError.message : String(lastError)})`);
|
|
148
153
|
}
|
|
@@ -199,6 +204,7 @@ class OwnedChromeProcess {
|
|
|
199
204
|
* (see `profile-lock.ts`) for `userDataDir` before calling.
|
|
200
205
|
*/
|
|
201
206
|
export async function launchChrome(options) {
|
|
207
|
+
options.signal?.throwIfAborted();
|
|
202
208
|
const executable = findChromeExecutable(options.executablePath);
|
|
203
209
|
const port = options.port ?? (await allocateEphemeralPort());
|
|
204
210
|
const args = buildChromeArgs({
|
|
@@ -218,7 +224,10 @@ export async function launchChrome(options) {
|
|
|
218
224
|
throw new Error(`Chrome exited immediately (code ${child.exitCode}).`);
|
|
219
225
|
}
|
|
220
226
|
try {
|
|
221
|
-
await waitForDevToolsEndpoint(port, {
|
|
227
|
+
await waitForDevToolsEndpoint(port, {
|
|
228
|
+
timeoutMs: options.readyTimeoutMs,
|
|
229
|
+
signal: options.signal,
|
|
230
|
+
});
|
|
222
231
|
}
|
|
223
232
|
catch (error) {
|
|
224
233
|
try {
|
|
@@ -284,6 +293,7 @@ export function buildFocusWindowScript(markerUrl) {
|
|
|
284
293
|
* launched Chrome. Resolves when the user closes the window.
|
|
285
294
|
*/
|
|
286
295
|
export async function launchSetupBrowser(options) {
|
|
296
|
+
options.signal?.throwIfAborted();
|
|
287
297
|
const executable = findChromeExecutable(options.executablePath);
|
|
288
298
|
const args = buildChromeArgs({
|
|
289
299
|
userDataDir: options.userDataDir,
|
|
@@ -291,9 +301,32 @@ export async function launchSetupBrowser(options) {
|
|
|
291
301
|
chromeArgs: options.chromeArgs,
|
|
292
302
|
});
|
|
293
303
|
const child = spawn(executable, args, { stdio: 'ignore', detached: false });
|
|
304
|
+
const browser = new OwnedChromeProcess(child, 0, '', options.userDataDir);
|
|
294
305
|
return new Promise((resolve, reject) => {
|
|
295
|
-
|
|
296
|
-
|
|
306
|
+
const cleanup = () => options.signal?.removeEventListener('abort', abort);
|
|
307
|
+
const abort = () => {
|
|
308
|
+
void browser.shutdown().then(() => {
|
|
309
|
+
cleanup();
|
|
310
|
+
reject(options.signal?.reason ?? new Error('Browser setup aborted.'));
|
|
311
|
+
}, (error) => {
|
|
312
|
+
cleanup();
|
|
313
|
+
reject(error);
|
|
314
|
+
});
|
|
315
|
+
};
|
|
316
|
+
child.once('error', (error) => {
|
|
317
|
+
cleanup();
|
|
318
|
+
reject(error);
|
|
319
|
+
});
|
|
320
|
+
child.once('exit', (code) => {
|
|
321
|
+
cleanup();
|
|
322
|
+
if (options.signal?.aborted)
|
|
323
|
+
reject(options.signal.reason);
|
|
324
|
+
else
|
|
325
|
+
resolve(code);
|
|
326
|
+
});
|
|
327
|
+
options.signal?.addEventListener('abort', abort, { once: true });
|
|
328
|
+
if (options.signal?.aborted)
|
|
329
|
+
abort();
|
|
297
330
|
});
|
|
298
331
|
}
|
|
299
332
|
//# sourceMappingURL=chrome-launcher.js.map
|
package/dist/client.js
CHANGED
|
@@ -89,6 +89,8 @@ export class DevToolsClient {
|
|
|
89
89
|
});
|
|
90
90
|
const client = new Client({ name: 'pi-browser-use', version: '0.1.0' }, { capabilities: {} });
|
|
91
91
|
this.client = client;
|
|
92
|
+
// MCP transport implements callback properties, not EventTarget.
|
|
93
|
+
// oxlint-disable-next-line unicorn/prefer-add-event-listener
|
|
92
94
|
transport.onerror = (error) => {
|
|
93
95
|
if (generation !== this.generation)
|
|
94
96
|
return;
|
|
@@ -96,9 +98,10 @@ export class DevToolsClient {
|
|
|
96
98
|
console.error(`[pi-browser-use] chrome-devtools-mcp transport error (${transportErrorCode ?? error.name})`);
|
|
97
99
|
void this.disconnectUnhealthyClient(generation);
|
|
98
100
|
};
|
|
101
|
+
// oxlint-disable-next-line unicorn/prefer-add-event-listener
|
|
99
102
|
transport.onclose = () => this.markDisconnected(generation);
|
|
100
103
|
try {
|
|
101
|
-
await client.connect(transport, signal ? { signal, timeout: MCP_TIMEOUT_MS } : { timeout: MCP_TIMEOUT_MS });
|
|
104
|
+
await client.connect(transport, signal ? { signal, timeout: MCP_TIMEOUT_MS } : { timeout: MCP_TIMEOUT_MS, signal });
|
|
102
105
|
if (generation !== this.generation)
|
|
103
106
|
return;
|
|
104
107
|
this.state = 'ready';
|
|
@@ -125,6 +128,8 @@ export class DevToolsClient {
|
|
|
125
128
|
: undefined;
|
|
126
129
|
const diagnostic = summarizeFailure(stderr, errorName, transportErrorCode ?? errorCode);
|
|
127
130
|
console.error(`[pi-browser-use] browser connection failed: ${diagnostic}`);
|
|
131
|
+
// Raw upstream causes can contain credentials; retain only the sanitized diagnostic.
|
|
132
|
+
// oxlint-disable-next-line preserve-caught-error
|
|
128
133
|
throw new Error(`Browser connection failed. ${diagnostic}`);
|
|
129
134
|
}
|
|
130
135
|
}
|
|
@@ -181,6 +186,7 @@ export class DevToolsClient {
|
|
|
181
186
|
do {
|
|
182
187
|
const result = await client.listTools(cursor ? { cursor } : undefined, {
|
|
183
188
|
timeout: MCP_TIMEOUT_MS,
|
|
189
|
+
signal,
|
|
184
190
|
});
|
|
185
191
|
allTools.push(...result.tools.map((t) => ({
|
|
186
192
|
name: t.name,
|
|
@@ -197,20 +203,23 @@ export class DevToolsClient {
|
|
|
197
203
|
if (!client)
|
|
198
204
|
throw new Error('Client not connected');
|
|
199
205
|
try {
|
|
200
|
-
return await client.callTool({ name, arguments: args }, undefined, { timeout: MCP_TIMEOUT_MS });
|
|
206
|
+
return await client.callTool({ name, arguments: args }, undefined, { timeout: MCP_TIMEOUT_MS, signal });
|
|
201
207
|
}
|
|
202
208
|
catch (error) {
|
|
203
209
|
if (signal?.aborted)
|
|
204
210
|
throw error;
|
|
205
211
|
if (this.state !== 'ready' || this.client !== client) {
|
|
212
|
+
// oxlint-disable-next-line preserve-caught-error -- upstream causes may contain secrets
|
|
206
213
|
throw new Error('Browser connection lost; retry the tool.');
|
|
207
214
|
}
|
|
208
215
|
const errorName = error instanceof Error ? error.name : 'UnknownError';
|
|
209
216
|
console.error(`[pi-browser-use] upstream tool call failed (${errorName})`);
|
|
210
217
|
// Existing mode fails most often on the consent gate: say so plainly.
|
|
211
218
|
if (this.config.sessionMode === 'existing') {
|
|
219
|
+
// oxlint-disable-next-line preserve-caught-error -- upstream causes may contain secrets
|
|
212
220
|
throw new Error('Browser tool call failed. If Chrome is showing an "Allow remote debugging?" prompt, click Allow and retry.');
|
|
213
221
|
}
|
|
222
|
+
// oxlint-disable-next-line preserve-caught-error -- upstream causes may contain secrets
|
|
214
223
|
throw new Error('Browser tool call failed.');
|
|
215
224
|
}
|
|
216
225
|
}
|
package/dist/config.d.ts
CHANGED
|
@@ -62,11 +62,11 @@ export type BrowserMode = 'fresh' | 'persistent' | 'existing';
|
|
|
62
62
|
* (headless unless headed is requested, so logins work without popups).
|
|
63
63
|
* Attach fields never carry across modes.
|
|
64
64
|
*/
|
|
65
|
-
export declare function resolveModeTarget(base: BrowserUseConfig, mode: BrowserMode, headed?: boolean): BrowserUseConfig;
|
|
65
|
+
export declare function resolveModeTarget(base: BrowserUseConfig, mode: BrowserMode, headed?: boolean, defaultProfileDir?: string): BrowserUseConfig;
|
|
66
66
|
/** Expand a leading ~/ in user-supplied paths (env interpolation covers ${} only). */
|
|
67
67
|
export declare function expandHome(path: string): string;
|
|
68
68
|
/** Merge user config over fresh-headless defaults. */
|
|
69
|
-
export declare function resolveConfig(config?: BrowserUseConfig): BrowserUseConfig;
|
|
69
|
+
export declare function resolveConfig(config?: BrowserUseConfig, defaultProfileDir?: string): BrowserUseConfig;
|
|
70
70
|
/** Convert config into CLI flags for the chrome-devtools-mcp subprocess. */
|
|
71
71
|
export declare function configToArgs(config: BrowserUseConfig): string[];
|
|
72
72
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.js
CHANGED
|
@@ -31,10 +31,11 @@ const DEFAULTS = {
|
|
|
31
31
|
* (headless unless headed is requested, so logins work without popups).
|
|
32
32
|
* Attach fields never carry across modes.
|
|
33
33
|
*/
|
|
34
|
-
export function resolveModeTarget(base, mode, headed = false) {
|
|
35
|
-
const { browserUrl: _browserUrl, wsEndpoint: _wsEndpoint, autoConnect: _autoConnect, mode: _mode, headed: _headed, ...rest } = base;
|
|
34
|
+
export function resolveModeTarget(base, mode, headed = false, defaultProfileDir = DEFAULT_PROFILE_DIR) {
|
|
35
|
+
const { browserUrl: _browserUrl, wsEndpoint: _wsEndpoint, wsHeaders: _wsHeaders, autoConnect: _autoConnect, mode: _mode, headed: _headed, ...rest } = base;
|
|
36
36
|
void _browserUrl;
|
|
37
37
|
void _wsEndpoint;
|
|
38
|
+
void _wsHeaders;
|
|
38
39
|
void _autoConnect;
|
|
39
40
|
void _mode;
|
|
40
41
|
void _headed;
|
|
@@ -44,11 +45,14 @@ export function resolveModeTarget(base, mode, headed = false) {
|
|
|
44
45
|
return { ...freshRest, sessionMode: 'isolated', headless: !headed, isolated: true };
|
|
45
46
|
}
|
|
46
47
|
if (mode === 'existing') {
|
|
47
|
-
// Attach to the user's running Chrome: drop
|
|
48
|
-
//
|
|
49
|
-
const { userDataDir: _userDataDir, isolated: _isolated, ...existingRest } = rest;
|
|
48
|
+
// Attach to the user's running Chrome: drop launch-only fields so MCP
|
|
49
|
+
// auto-connects instead of trying to start or reconfigure its browser.
|
|
50
|
+
const { userDataDir: _userDataDir, isolated: _isolated, executablePath: _executablePath, chromeArgs: _chromeArgs, viewport: _viewport, ...existingRest } = rest;
|
|
50
51
|
void _userDataDir;
|
|
51
52
|
void _isolated;
|
|
53
|
+
void _executablePath;
|
|
54
|
+
void _chromeArgs;
|
|
55
|
+
void _viewport;
|
|
52
56
|
// Existing attaches to the user's visible Chrome: always headed.
|
|
53
57
|
return { ...existingRest, sessionMode: 'existing', headless: false, autoConnect: true };
|
|
54
58
|
}
|
|
@@ -57,7 +61,7 @@ export function resolveModeTarget(base, mode, headed = false) {
|
|
|
57
61
|
sessionMode: 'persistent',
|
|
58
62
|
headless: !headed,
|
|
59
63
|
isolated: false,
|
|
60
|
-
userDataDir: base.userDataDir ??
|
|
64
|
+
userDataDir: base.userDataDir ?? defaultProfileDir,
|
|
61
65
|
};
|
|
62
66
|
}
|
|
63
67
|
/** Expand a leading ~/ in user-supplied paths (env interpolation covers ${} only). */
|
|
@@ -65,7 +69,7 @@ export function expandHome(path) {
|
|
|
65
69
|
return path === '~' ? homedir() : path.startsWith('~/') ? resolve(homedir(), path.slice(2)) : path;
|
|
66
70
|
}
|
|
67
71
|
/** Merge user config over fresh-headless defaults. */
|
|
68
|
-
export function resolveConfig(config) {
|
|
72
|
+
export function resolveConfig(config, defaultProfileDir = DEFAULT_PROFILE_DIR) {
|
|
69
73
|
const { mode, headed, ...rest } = config ?? {};
|
|
70
74
|
const resolved = { ...DEFAULTS, ...rest };
|
|
71
75
|
if (typeof resolved.userDataDir === 'string')
|
|
@@ -116,7 +120,7 @@ export function resolveConfig(config) {
|
|
|
116
120
|
break;
|
|
117
121
|
default:
|
|
118
122
|
if (!resolved.userDataDir && !resolved.browserUrl && !resolved.wsEndpoint) {
|
|
119
|
-
resolved.userDataDir =
|
|
123
|
+
resolved.userDataDir = defaultProfileDir;
|
|
120
124
|
}
|
|
121
125
|
break;
|
|
122
126
|
}
|
package/dist/existing-flow.js
CHANGED
|
@@ -78,7 +78,9 @@ export function parseMcpPageList(result) {
|
|
|
78
78
|
const title = (match[2] ?? '').trim();
|
|
79
79
|
if (title)
|
|
80
80
|
entry.title = title;
|
|
81
|
-
|
|
81
|
+
// chrome-devtools-mcp 1.8 emits `N: URL [selected]`; retain support
|
|
82
|
+
// for the older `N: title (URL)` form as well.
|
|
83
|
+
const url = (match[3] ?? (/^(https?:|about:|file:|data:)/.test(title) ? title : '')).trim();
|
|
82
84
|
if (url)
|
|
83
85
|
entry.url = url;
|
|
84
86
|
entries.push(entry);
|
|
@@ -113,7 +115,7 @@ export async function openExistingPage(url, deps, options) {
|
|
|
113
115
|
}
|
|
114
116
|
catch (error) {
|
|
115
117
|
throw new Error(`Pi extension did not open the tab (token ${token}). ` +
|
|
116
|
-
`Is the extension installed and polling the tab bridge? (${error instanceof Error ? error.message : String(error)})
|
|
118
|
+
`Is the extension installed and polling the tab bridge? (${error instanceof Error ? error.message : String(error)})`, { cause: error });
|
|
117
119
|
}
|
|
118
120
|
let pageId;
|
|
119
121
|
try {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,47 +1,20 @@
|
|
|
1
|
+
import { createRegistryVisionCaller } from './vision.js';
|
|
1
2
|
export { configToArgs, resolveConfig } from './config.js';
|
|
2
|
-
|
|
3
|
-
find(provider: string, modelId: string): unknown;
|
|
4
|
-
getApiKeyAndHeaders(model: unknown): Promise<{
|
|
5
|
-
ok: true;
|
|
6
|
-
apiKey?: string;
|
|
7
|
-
headers?: Record<string, string>;
|
|
8
|
-
} | {
|
|
9
|
-
ok: false;
|
|
10
|
-
error: string;
|
|
11
|
-
}>;
|
|
12
|
-
}
|
|
13
|
-
interface PiToolContext {
|
|
14
|
-
modelRegistry?: ModelRegistry;
|
|
15
|
-
}
|
|
3
|
+
type ModelRegistry = Parameters<typeof createRegistryVisionCaller>[1];
|
|
16
4
|
interface Pi {
|
|
17
|
-
registerTool(
|
|
5
|
+
registerTool(definition: {
|
|
18
6
|
name: string;
|
|
19
7
|
label: string;
|
|
20
8
|
description: string;
|
|
21
9
|
parameters: unknown;
|
|
22
|
-
execute: (toolCallId: string, params: Record<string, unknown>, signal?: AbortSignal, onUpdate?: unknown,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
text?: string;
|
|
26
|
-
data?: string;
|
|
27
|
-
mimeType?: string;
|
|
28
|
-
}>;
|
|
29
|
-
isError?: boolean;
|
|
30
|
-
details?: undefined;
|
|
31
|
-
}>;
|
|
10
|
+
execute: (toolCallId: string, params: Record<string, unknown>, signal?: AbortSignal, onUpdate?: unknown, context?: {
|
|
11
|
+
modelRegistry?: ModelRegistry;
|
|
12
|
+
}) => Promise<unknown>;
|
|
32
13
|
}): void;
|
|
33
|
-
on(event: string, handler: (event: unknown,
|
|
14
|
+
on(event: string, handler: (event: unknown, context: {
|
|
34
15
|
cwd: string;
|
|
35
16
|
} & Record<string, unknown>) => Promise<void>): void;
|
|
36
17
|
}
|
|
37
|
-
/**
|
|
38
|
-
* Pi extension entry point. On session_start spawns chrome-devtools-mcp,
|
|
39
|
-
* discovers upstream tools, and registers each as browser_*. On
|
|
40
|
-
* session_shutdown tears the subprocess down. Nothing runs persistently.
|
|
41
|
-
*
|
|
42
|
-
* Defaults are persistent headless (Pi-owned profile, no window, no consent
|
|
43
|
-
* popups). Set mode "fresh" for an isolated clean room, or "existing" with
|
|
44
|
-
* autoConnect/browserUrl to drive an already-running Chrome.
|
|
45
|
-
*/
|
|
18
|
+
/** Native Pi owns settings/trust and model credentials, not browser behavior. */
|
|
46
19
|
export default function browserUseExtension(pi: Pi): void;
|
|
47
20
|
//# sourceMappingURL=index.d.ts.map
|