Sign In

@panerelay/bridge

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@panerelay/bridge - npm Package Compare versions

Comparing version
0.3.0
to
0.4.0
+21
dist/browser-use-gateway.d.ts
export declare const PANERELAY_BROWSER_USE_GATEWAY_PROTOCOL: "panerelay.browser-use-gateway.v1";
export declare const PANERELAY_BROWSER_USE_GATEWAY_PORT = 43827;
export interface BrowserUseGatewayState {
protocol: typeof PANERELAY_BROWSER_USE_GATEWAY_PROTOCOL;
port: number;
pid: number;
updatedAt: string;
}
export type BrowserUseGatewayStopResult = 'absent' | 'stopped' | 'remaining';
export declare function browserUseGatewayStatePath(homeDirectory?: string): string;
export declare function browserUseGatewayUrl(port?: number): string;
export declare function runBrowserUseGateway(options?: {
homeDirectory?: string;
}): Promise<void>;
export declare function stopBrowserUseGateway(options?: {
homeDirectory?: string;
}): Promise<BrowserUseGatewayStopResult>;
export declare function ensureBrowserUseGateway(options?: {
homeDirectory?: string;
}): Promise<string>;
//# sourceMappingURL=browser-use-gateway.d.ts.map
{"version":3,"file":"browser-use-gateway.d.ts","sourceRoot":"","sources":["../src/browser-use-gateway.ts"],"names":[],"mappings":"AAmBA,eAAO,MAAM,sCAAsC,EAAG,kCAA2C,CAAC;AAClG,eAAO,MAAM,kCAAkC,QAAQ,CAAC;AAIxD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,OAAO,sCAAsC,CAAC;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,2BAA2B,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;AAE7E,wBAAgB,0BAA0B,CAAC,aAAa,SAAY,GAAG,MAAM,CAE5E;AAED,wBAAgB,oBAAoB,CAAC,IAAI,SAAqC,GAAG,MAAM,CAEtF;AAoOD,wBAAsB,oBAAoB,CACxC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GACvC,OAAO,CAAC,IAAI,CAAC,CAkDf;AAED,wBAAsB,qBAAqB,CACzC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GACvC,OAAO,CAAC,2BAA2B,CAAC,CAwCtC;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GACvC,OAAO,CAAC,MAAM,CAAC,CA8CjB"}
import { randomBytes } from 'node:crypto';
import { createServer } from 'node:http';
import { mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { spawn } from 'node:child_process';
import { PANERELAY_BROWSER_ENV, PANERELAY_BROWSER_ID_ENV, selectBrowserRegistration, } from '@panerelay/browser-registry';
import { PANERELAY_BROWSER_USE_GATEWAY_PATH, parseBrowserUseGatewaySelection, } from '@panerelay/browser-use/environment';
import { PANERELAY_PROTOCOL_VERSION } from '@panerelay/protocol';
export const PANERELAY_BROWSER_USE_GATEWAY_PROTOCOL = 'panerelay.browser-use-gateway.v1';
export const PANERELAY_BROWSER_USE_GATEWAY_PORT = 43827;
const MAX_GATEWAY_RESPONSE_BYTES = 16 * 1024;
const BOOTSTRAP_TICKET_PATTERN = /^[A-Za-z0-9_-]{43}$/;
export function browserUseGatewayStatePath(homeDirectory = homedir()) {
return join(homeDirectory, '.panerelay', 'browser-use', 'gateway.json');
}
export function browserUseGatewayUrl(port = PANERELAY_BROWSER_USE_GATEWAY_PORT) {
return `http://127.0.0.1:${port}${PANERELAY_BROWSER_USE_GATEWAY_PATH}`;
}
async function json(response, status, value) {
const body = JSON.stringify(value);
response.writeHead(status, {
'cache-control': 'no-store',
'content-type': 'application/json',
'content-length': Buffer.byteLength(body),
});
response.end(body);
}
function gatewayRegistryOptions(homeDirectory) {
return {
defaultPath: join(homeDirectory, '.panerelay', 'browser-default.json'),
environment: gatewaySelectionEnvironment(),
legacyPath: join(homeDirectory, '.panerelay', 'bridge.json'),
registryDirectory: join(homeDirectory, '.panerelay', 'browsers'),
};
}
function gatewaySelectionEnvironment(selection) {
const environment = { ...process.env };
delete environment[PANERELAY_BROWSER_ID_ENV];
delete environment[PANERELAY_BROWSER_ENV];
if (selection)
environment[PANERELAY_BROWSER_ID_ENV] = selection.browserId;
return environment;
}
async function boundedText(response) {
const contentLength = Number(response.headers.get('content-length'));
if (Number.isFinite(contentLength) && contentLength > MAX_GATEWAY_RESPONSE_BYTES) {
throw new Error('Gateway response exceeded the protocol limit');
}
if (!response.body) {
const body = await response.text();
if (Buffer.byteLength(body) > MAX_GATEWAY_RESPONSE_BYTES) {
throw new Error('Gateway response exceeded the protocol limit');
}
return body;
}
const reader = response.body.getReader();
const chunks = [];
let size = 0;
try {
while (true) {
const chunk = await reader.read();
if (chunk.done)
break;
size += chunk.value.byteLength;
if (size > MAX_GATEWAY_RESPONSE_BYTES) {
await reader.cancel();
throw new Error('Gateway response exceeded the protocol limit');
}
chunks.push(chunk.value);
}
}
finally {
reader.releaseLock();
}
return Buffer.concat(chunks.map(chunk => Buffer.from(chunk))).toString('utf8');
}
function controlledWebSocketUrl(value) {
if (typeof value !== 'string' || value.length > 2_048)
return false;
try {
const url = new URL(value);
const queryKeys = [...url.searchParams.keys()];
return (url.protocol === 'ws:' &&
url.hostname === '127.0.0.1' &&
url.port !== '' &&
url.username === '' &&
url.password === '' &&
url.pathname === '/cdp' &&
url.searchParams.getAll('session').length === 1 &&
url.searchParams.get('session') !== '' &&
url.searchParams.getAll('token').length === 1 &&
url.searchParams.get('token') !== '' &&
queryKeys.every(key => key === 'session' || key === 'token') &&
url.hash === '');
}
catch {
return false;
}
}
function controlledVersionMetadata(value) {
if (!value || typeof value !== 'object' || Array.isArray(value))
return false;
const keys = Object.keys(value).sort();
const expectedKeys = [
'Browser',
'Protocol-Version',
'User-Agent',
'V8-Version',
'WebKit-Version',
'webSocketDebuggerUrl',
].sort();
if (keys.length !== expectedKeys.length ||
!keys.every((key, index) => key === expectedKeys[index])) {
return false;
}
const metadata = value;
return (typeof metadata.Browser === 'string' &&
metadata.Browser.length > 0 &&
metadata.Browser.length <= 512 &&
typeof metadata['Protocol-Version'] === 'string' &&
metadata['Protocol-Version'].length > 0 &&
metadata['Protocol-Version'].length <= 128 &&
typeof metadata['User-Agent'] === 'string' &&
metadata['User-Agent'].length > 0 &&
metadata['User-Agent'].length <= 512 &&
typeof metadata['V8-Version'] === 'string' &&
metadata['V8-Version'].length > 0 &&
metadata['V8-Version'].length <= 512 &&
typeof metadata['WebKit-Version'] === 'string' &&
metadata['WebKit-Version'].length > 0 &&
metadata['WebKit-Version'].length <= 512 &&
controlledWebSocketUrl(metadata.webSocketDebuggerUrl));
}
function controlledBootstrapUrl(value) {
if (typeof value !== 'string' || value.length > 4_096)
return false;
try {
const url = new URL(value);
return (url.protocol === 'http:' &&
url.hostname === '127.0.0.1' &&
url.port !== '' &&
url.username === '' &&
url.password === '' &&
url.pathname.startsWith('/cdp/bootstrap/') &&
BOOTSTRAP_TICKET_PATTERN.test(url.pathname.slice('/cdp/bootstrap/'.length)) &&
url.search === '' &&
url.hash === '');
}
catch {
return false;
}
}
async function proxyVersion(response, homeDirectory, selection) {
try {
const selected = await selectBrowserRegistration({
...gatewayRegistryOptions(homeDirectory),
environment: gatewaySelectionEnvironment(selection),
});
if (selection && selected.state.generation !== selection.generation) {
throw new Error('The selected browser connection changed; resolve it again');
}
const bootstrap = await fetch(`http://127.0.0.1:${selected.state.port}/cdp/bootstrap`, {
method: 'POST',
headers: {
authorization: `Bearer ${selected.state.token}`,
'content-type': 'application/json',
},
body: JSON.stringify({
protocol: PANERELAY_PROTOCOL_VERSION,
browser: {
browserId: selected.state.browserId,
generation: selected.state.generation,
},
actor: { kind: 'automation', name: 'Browser Use', sessionLabel: 'panerelay' },
engine: 'browser-use',
laneKey: 'browser-use:panerelay',
connectionPolicy: 'single',
}),
signal: AbortSignal.timeout(5_000),
});
if (bootstrap.status !== 201) {
await json(response, bootstrap.status === 429 ? 429 : 503, {
protocol: PANERELAY_BROWSER_USE_GATEWAY_PROTOCOL,
error: 'Panerelay Browser Use connection is unavailable',
});
return;
}
const createdText = await boundedText(bootstrap);
const created = JSON.parse(createdText);
if (!controlledBootstrapUrl(created.cdpUrl))
throw new Error('invalid bootstrap response');
const version = await fetch(`${created.cdpUrl}/json/version`, {
signal: AbortSignal.timeout(5_000),
});
if (version.status !== 200)
throw new Error('invalid Browser Use version response');
const metadata = JSON.parse(await boundedText(version));
if (!controlledVersionMetadata(metadata))
throw new Error('invalid Browser Use version response');
await json(response, 200, metadata);
}
catch {
await json(response, 503, {
protocol: PANERELAY_BROWSER_USE_GATEWAY_PROTOCOL,
error: 'Panerelay Browser Use connection is unavailable',
});
}
}
async function gatewayHealthState(port) {
const response = await fetch(`http://127.0.0.1:${port}/health`, {
signal: AbortSignal.timeout(500),
});
if (!response.ok)
return null;
try {
const body = JSON.parse(await boundedText(response));
return body.protocol === PANERELAY_BROWSER_USE_GATEWAY_PROTOCOL &&
body.ready === true &&
typeof body.pid === 'number' &&
Number.isSafeInteger(body.pid) &&
body.pid > 0
? { pid: body.pid, protocol: body.protocol }
: null;
}
catch {
return null;
}
}
async function gatewayHealth(port) {
return (await gatewayHealthState(port)) !== null;
}
export async function runBrowserUseGateway(options = {}) {
const homeDirectory = options.homeDirectory ?? homedir();
const path = browserUseGatewayStatePath(homeDirectory);
const server = createServer(async (request, response) => {
const url = new URL(request.url ?? '/', 'http://127.0.0.1');
if (request.method === 'GET' && url.pathname === '/health' && url.search === '') {
await json(response, 200, {
pid: process.pid,
protocol: PANERELAY_BROWSER_USE_GATEWAY_PROTOCOL,
ready: true,
});
return;
}
if (request.method === 'GET' && url.search === '') {
const selection = parseBrowserUseGatewaySelection(url.pathname);
if (selection !== null) {
await proxyVersion(response, homeDirectory, selection);
return;
}
}
await json(response, 404, {
protocol: PANERELAY_BROWSER_USE_GATEWAY_PROTOCOL,
error: 'Unknown Panerelay Browser Use gateway endpoint',
});
});
await new Promise((resolve, reject) => {
server.once('error', reject);
server.listen(PANERELAY_BROWSER_USE_GATEWAY_PORT, '127.0.0.1', resolve);
});
await mkdir(join(homeDirectory, '.panerelay', 'browser-use'), { recursive: true, mode: 0o700 });
const state = {
protocol: PANERELAY_BROWSER_USE_GATEWAY_PROTOCOL,
port: PANERELAY_BROWSER_USE_GATEWAY_PORT,
pid: process.pid,
updatedAt: new Date().toISOString(),
};
const temporary = `${path}.${process.pid}.${randomBytes(6).toString('hex')}.tmp`;
await writeFile(temporary, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
await rename(temporary, path);
const cleanup = async () => {
try {
const current = JSON.parse(await readFile(path, 'utf8'));
if (current.pid === process.pid)
await rm(path, { force: true });
}
catch {
// The state may already have been removed or replaced by a newer owner.
}
server.close();
};
process.once('SIGTERM', () => void cleanup().finally(() => process.exit(0)));
process.once('SIGINT', () => void cleanup().finally(() => process.exit(0)));
}
export async function stopBrowserUseGateway(options = {}) {
const homeDirectory = options.homeDirectory ?? homedir();
const path = browserUseGatewayStatePath(homeDirectory);
let state;
try {
state = JSON.parse(await readFile(path, 'utf8'));
}
catch (error) {
if (error.code === 'ENOENT')
return 'absent';
return 'remaining';
}
if (state.protocol !== PANERELAY_BROWSER_USE_GATEWAY_PROTOCOL ||
state.port !== PANERELAY_BROWSER_USE_GATEWAY_PORT ||
typeof state.pid !== 'number' ||
!Number.isSafeInteger(state.pid) ||
state.pid <= 0) {
return 'remaining';
}
let health;
try {
health = await gatewayHealthState(state.port);
}
catch {
health = null;
}
if (!health || health.pid !== state.pid)
return 'remaining';
try {
process.kill(state.pid, 'SIGTERM');
}
catch (error) {
if (error.code !== 'ESRCH')
return 'remaining';
}
for (let attempt = 0; attempt < 20; attempt += 1) {
await new Promise(resolve => setTimeout(resolve, 50));
try {
if (!(await gatewayHealth(state.port)))
return 'stopped';
}
catch {
return 'stopped';
}
}
return 'remaining';
}
export async function ensureBrowserUseGateway(options = {}) {
const homeDirectory = options.homeDirectory ?? homedir();
const path = browserUseGatewayStatePath(homeDirectory);
try {
const state = JSON.parse(await readFile(path, 'utf8'));
if (state.protocol === PANERELAY_BROWSER_USE_GATEWAY_PROTOCOL &&
state.port === PANERELAY_BROWSER_USE_GATEWAY_PORT &&
(await gatewayHealth(state.port))) {
return browserUseGatewayUrl(state.port);
}
}
catch {
// Start or recover the gateway below.
}
const entry = process.argv[1];
if (!entry)
throw new Error('Panerelay Browser Use gateway entrypoint is unavailable');
const gatewayEnvironment = {
...process.env,
HOME: homeDirectory,
USERPROFILE: homeDirectory,
};
delete gatewayEnvironment[PANERELAY_BROWSER_ID_ENV];
delete gatewayEnvironment[PANERELAY_BROWSER_ENV];
const child = spawn(process.execPath, [entry, '--browser-use-gateway'], {
detached: true,
stdio: 'ignore',
env: gatewayEnvironment,
});
child.unref();
for (let attempt = 0; attempt < 50; attempt += 1) {
await new Promise(resolve => setTimeout(resolve, 100));
try {
const state = JSON.parse(await readFile(path, 'utf8'));
if (state.protocol === PANERELAY_BROWSER_USE_GATEWAY_PROTOCOL &&
state.port === PANERELAY_BROWSER_USE_GATEWAY_PORT &&
(await gatewayHealth(state.port))) {
return browserUseGatewayUrl(state.port);
}
}
catch {
// Keep waiting for the detached gateway to bind.
}
}
throw new Error('Panerelay Browser Use gateway did not become ready');
}
+4
-1
import { type BridgeState, type HostToExtensionMessage, type IntegrationRequestMessage } from '@panerelay/protocol';
import { type CliAdapterRegistration } from '@panerelay/cli/adapter-config';
import { setCliAdapterMode, type CliAdapterRegistration } from '@panerelay/cli/adapter-config';
import { setBrowserUseEnvironmentMode } from '@panerelay/browser-use';
import { clearBrowserDefault, listBrowserRegistrations, readBrowserDefault, setBrowserDefault } from '@panerelay/browser-registry';

@@ -19,2 +20,4 @@ import { clearPanerelayUserDefaultProvider, readPanerelayProviderAvailable, readUserDefaultProvider, setPanerelayUserDefaultProvider } from './agent-browser-config.js';

setBrowserDefault?: typeof setBrowserDefault;
setBrowserUseEnvironmentMode?: typeof setBrowserUseEnvironmentMode;
setCliAdapterMode?: typeof setCliAdapterMode;
setBrowserUseMode?: (mode: 'direct' | 'extension') => Promise<void>;

@@ -21,0 +24,0 @@ setDefaultProvider?: typeof setPanerelayUserDefaultProvider;

+1
-1

@@ -1,1 +0,1 @@

{"version":3,"file":"integration-service.d.ts","sourceRoot":"","sources":["../src/integration-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAI3B,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAIL,KAAK,sBAAsB,EAC5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,iCAAiC,EACjC,8BAA8B,EAC9B,uBAAuB,EACvB,+BAA+B,EAEhC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAE1E,MAAM,WAAW,yBAAyB;IACxC,mBAAmB,CAAC,EAAE,OAAO,mBAAmB,CAAC;IACjD,oBAAoB,CAAC,EAAE,OAAO,iCAAiC,CAAC;IAChE,cAAc,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IAC1C,kBAAkB,CAAC,EAAE,OAAO,4BAA4B,CAAC;IACzD,YAAY,CAAC,EAAE,OAAO,wBAAwB,CAAC;IAC/C,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IACrE,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC,QAAQ,GAAG,WAAW,GAAG,IAAI,CAAC,CAAC;IAClE,kBAAkB,CAAC,EAAE,OAAO,kBAAkB,CAAC;IAC/C,mBAAmB,CAAC,EAAE,OAAO,uBAAuB,CAAC;IACrD,wBAAwB,CAAC,EAAE,OAAO,8BAA8B,CAAC;IACjE,iBAAiB,CAAC,EAAE,OAAO,iBAAiB,CAAC;IAC7C,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,GAAG,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,kBAAkB,CAAC,EAAE,OAAO,+BAA+B,CAAC;IAC5D,aAAa,CAAC,EAAE,OAAO,sBAAsB,CAAC;CAC/C;AAiDD,qBAAa,kBAAkB;;gBAmB3B,IAAI,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,IAAI,EAC/C,OAAO,GAAE,yBAA8B;IA+BnC,MAAM,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC;CA+KhE"}
{"version":3,"file":"integration-service.d.ts","sourceRoot":"","sources":["../src/integration-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAI3B,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,iBAAiB,EACjB,KAAK,sBAAsB,EAC5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,iCAAiC,EACjC,8BAA8B,EAC9B,uBAAuB,EACvB,+BAA+B,EAEhC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAE1E,MAAM,WAAW,yBAAyB;IACxC,mBAAmB,CAAC,EAAE,OAAO,mBAAmB,CAAC;IACjD,oBAAoB,CAAC,EAAE,OAAO,iCAAiC,CAAC;IAChE,cAAc,CAAC,EAAE,MAAM,WAAW,GAAG,IAAI,CAAC;IAC1C,kBAAkB,CAAC,EAAE,OAAO,4BAA4B,CAAC;IACzD,YAAY,CAAC,EAAE,OAAO,wBAAwB,CAAC;IAC/C,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;IACrE,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC,QAAQ,GAAG,WAAW,GAAG,IAAI,CAAC,CAAC;IAClE,kBAAkB,CAAC,EAAE,OAAO,kBAAkB,CAAC;IAC/C,mBAAmB,CAAC,EAAE,OAAO,uBAAuB,CAAC;IACrD,wBAAwB,CAAC,EAAE,OAAO,8BAA8B,CAAC;IACjE,iBAAiB,CAAC,EAAE,OAAO,iBAAiB,CAAC;IAC7C,4BAA4B,CAAC,EAAE,OAAO,4BAA4B,CAAC;IACnE,iBAAiB,CAAC,EAAE,OAAO,iBAAiB,CAAC;IAC7C,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,GAAG,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,kBAAkB,CAAC,EAAE,OAAO,+BAA+B,CAAC;IAC5D,aAAa,CAAC,EAAE,OAAO,sBAAsB,CAAC;CAC/C;AAiDD,qBAAa,kBAAkB;;gBAqB3B,IAAI,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,IAAI,EAC/C,OAAO,GAAE,yBAA8B;IAsCnC,MAAM,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC;CA+KhE"}
import { PANERELAY_PROTOCOL_VERSION, } from '@panerelay/protocol';
import { readCliAdapterMode, readCliAdapterRegistration, setCliAdapterMode, } from '@panerelay/cli/adapter-config';
import { setBrowserUseEnvironmentMode } from '@panerelay/browser-use';
import { clearBrowserDefault, listBrowserRegistrations, readBrowserDefault, setBrowserDefault, } from '@panerelay/browser-registry';

@@ -54,2 +55,4 @@ import { clearPanerelayUserDefaultProvider, readPanerelayProviderAvailable, readUserDefaultProvider, setPanerelayUserDefaultProvider, } from './agent-browser-config.js';

#setBrowserDefault;
#setBrowserUseEnvironmentMode;
#setCliAdapterMode;
#setBrowserUseMode;

@@ -74,4 +77,11 @@ #setDefaultProvider;

this.#setBrowserDefault = options.setBrowserDefault ?? setBrowserDefault;
this.#setBrowserUseEnvironmentMode =
options.setBrowserUseEnvironmentMode ?? setBrowserUseEnvironmentMode;
this.#setCliAdapterMode = options.setCliAdapterMode ?? setCliAdapterMode;
this.#setBrowserUseMode =
options.setBrowserUseMode ?? (mode => setCliAdapterMode('browser-use', mode));
options.setBrowserUseMode ??
(async (mode) => {
await this.#setBrowserUseEnvironmentMode(mode);
await this.#setCliAdapterMode('browser-use', mode);
});
this.#setDefaultProvider = options.setDefaultProvider ?? setPanerelayUserDefaultProvider;

@@ -78,0 +88,0 @@ this.#pickDirectory = options.pickDirectory ?? pickWorkspaceDirectory;

@@ -10,2 +10,3 @@ #!/usr/bin/env node

import { IntegrationService } from './integration-service.js';
import { ensureBrowserUseGateway, runBrowserUseGateway } from './browser-use-gateway.js';
function log(message) {

@@ -70,2 +71,3 @@ process.stderr.write(`[Panerelay] ${message}\n`);

log(`Extension registered; CDP relay listening on 127.0.0.1:${relay.port}`);
await ensureBrowserUseGateway().catch(error => log(`Browser Use gateway unavailable: ${error instanceof Error ? error.message : String(error)}`));
},

@@ -150,5 +152,7 @@ onBrowserDisconnected: async () => {

}
const operation = process.argv.includes('--agent-browser-plugin')
? runAgentBrowserPlugin()
: main();
const operation = process.argv.includes('--browser-use-gateway')
? runBrowserUseGateway()
: process.argv.includes('--agent-browser-plugin')
? runAgentBrowserPlugin()
: main();
void operation.catch(error => {

@@ -155,0 +159,0 @@ log(`Bridge failed to start: ${error instanceof Error ? error.message : String(error)}`);

{
"name": "@panerelay/bridge",
"version": "0.3.0",
"version": "0.4.0",
"description": "Panerelay Native Messaging host and local browser-level CDP relay.",

@@ -38,2 +38,6 @@ "type": "module",

"import": "./dist/agent-browser-config.js"
},
"./browser-use-gateway": {
"types": "./dist/browser-use-gateway.d.ts",
"import": "./dist/browser-use-gateway.js"
}

@@ -54,10 +58,9 @@ },

"ws": "^8.21.1",
"@panerelay/agent-browser": "0.3.0",
"@panerelay/browser-registry": "0.3.0",
"@panerelay/cli": "0.3.0",
"@panerelay/protocol": "0.3.0"
"@panerelay/agent-browser": "0.4.0",
"@panerelay/browser-registry": "0.4.0",
"@panerelay/browser-use": "0.4.0",
"@panerelay/cli": "0.4.0",
"@panerelay/protocol": "0.4.0"
},
"devDependencies": {
"@panerelay/browser-use": "0.3.0"
},
"devDependencies": {},
"scripts": {

@@ -64,0 +67,0 @@ "build": "node clean.mjs && tsc -p tsconfig.json && node build.mjs",

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display