@browserbridge/bbx 1.7.5 → 1.7.6
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/package.json +6 -6
- package/packages/agent-client/src/cli-args.js +152 -0
- package/packages/agent-client/src/cli-batch.js +140 -0
- package/packages/agent-client/src/cli-output.js +57 -0
- package/packages/agent-client/src/cli-proxy-remote.js +350 -0
- package/packages/agent-client/src/cli-setup-commands.js +404 -0
- package/packages/agent-client/src/cli.js +22 -1062
- package/packages/agent-client/src/runtime.js +1 -2
- package/packages/native-host/src/auth-token.js +1 -1
- package/packages/native-host/src/config.js +9 -4
- package/packages/native-host/src/daemon-process.js +8 -1
- package/packages/protocol/src/capabilities.js +33 -110
- package/packages/protocol/src/capability-values.js +45 -0
- package/packages/protocol/src/defaults.js +17 -2
- package/packages/protocol/src/registry.js +299 -86
|
@@ -433,8 +433,7 @@ export async function getDoctorReport(options = {}) {
|
|
|
433
433
|
if (!response.ok) {
|
|
434
434
|
throw new Error(response.error.message);
|
|
435
435
|
}
|
|
436
|
-
const result =
|
|
437
|
-
/** @type {{ daemon?: string, extensionConnected?: boolean, access?: {
|
|
436
|
+
const result = /** @type {{ daemon?: string, extensionConnected?: boolean, access?: {
|
|
438
437
|
enabled?: boolean,
|
|
439
438
|
windowId?: number | null,
|
|
440
439
|
routeTabId?: number | null,
|
|
@@ -60,7 +60,7 @@ export async function readBridgeAuthTokenOverride(options = {}) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
|
-
* @param {{ tokenPath?: string, readFile?: typeof fs.promises.readFile }} [options={}]
|
|
63
|
+
* @param {{ env?: NodeJS.ProcessEnv, tokenPath?: string, readFile?: typeof fs.promises.readFile }} [options={}]
|
|
64
64
|
* @returns {Promise<string | null>}
|
|
65
65
|
*/
|
|
66
66
|
export async function readBridgeAuthToken(options = {}) {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import os from 'node:os';
|
|
5
5
|
import path from 'node:path';
|
|
6
|
+
import { createHash } from 'node:crypto';
|
|
6
7
|
|
|
7
8
|
export const APP_NAME = 'com.browserbridge.browser_bridge';
|
|
8
9
|
export const BRIDGE_HOME_ENV = 'BROWSER_BRIDGE_HOME';
|
|
@@ -62,15 +63,19 @@ export function getBridgeDir(env = process.env) {
|
|
|
62
63
|
* connect to. On Windows we use a Named Pipe by default because Node's AF_UNIX
|
|
63
64
|
* support fails with EACCES on listen() under recent Node + Windows 11
|
|
64
65
|
* combinations, while Named Pipes are the historical and reliable Windows IPC
|
|
65
|
-
* mechanism.
|
|
66
|
-
*
|
|
66
|
+
* mechanism. Custom bridge homes use a stable suffix so isolated daemon and
|
|
67
|
+
* test setups do not contend for the default pipe.
|
|
67
68
|
*
|
|
68
69
|
* @param {NodeJS.ProcessEnv} [env=process.env]
|
|
69
70
|
* @returns {string}
|
|
70
71
|
*/
|
|
71
72
|
export function getSocketPath(env = process.env) {
|
|
72
|
-
if (os.platform() === 'win32'
|
|
73
|
-
|
|
73
|
+
if (os.platform() === 'win32') {
|
|
74
|
+
const bridgeHome = env[BRIDGE_HOME_ENV];
|
|
75
|
+
const suffix = bridgeHome
|
|
76
|
+
? `-${createHash('sha256').update(bridgeHome.toLowerCase()).digest('hex').slice(0, 16)}`
|
|
77
|
+
: '';
|
|
78
|
+
return `\\\\.\\pipe\\${APP_NAME}${suffix}`;
|
|
74
79
|
}
|
|
75
80
|
return path.join(getBridgeDir(env), 'bridge.sock');
|
|
76
81
|
}
|
|
@@ -407,10 +407,17 @@ async function restartBridgeDaemonAfterStop(stopResult, options = {}) {
|
|
|
407
407
|
throw new Error('Timed out waiting for Browser Bridge daemon to start.');
|
|
408
408
|
}
|
|
409
409
|
|
|
410
|
+
let pid = await readPidFn(pidPath);
|
|
411
|
+
if (pid === null) {
|
|
412
|
+
// The daemon starts listening immediately before it persists its PID.
|
|
413
|
+
await sleepFn(pollIntervalMs);
|
|
414
|
+
pid = await readPidFn(pidPath);
|
|
415
|
+
}
|
|
416
|
+
|
|
410
417
|
return {
|
|
411
418
|
...stopResult,
|
|
412
419
|
pidPath,
|
|
413
|
-
pid
|
|
420
|
+
pid,
|
|
414
421
|
};
|
|
415
422
|
}
|
|
416
423
|
|
|
@@ -1,122 +1,45 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
import { CAPABILITIES, DEFAULT_CAPABILITIES } from './capability-values.js';
|
|
4
|
+
import { BRIDGE_METHODS, BRIDGE_METHOD_REGISTRY } from './registry.js';
|
|
5
|
+
|
|
3
6
|
/** @typedef {import('./types.js').BridgeMethod} CapabilityMethod */
|
|
4
7
|
/** @typedef {import('./types.js').Capability} Capability */
|
|
5
8
|
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
TABS_MANAGE: 'tabs.manage',
|
|
23
|
-
PERFORMANCE_READ: 'performance.read',
|
|
24
|
-
NETWORK_READ: 'network.read',
|
|
25
|
-
NETWORK_INTERCEPT: 'network.intercept',
|
|
26
|
-
});
|
|
9
|
+
export { CAPABILITIES, DEFAULT_CAPABILITIES };
|
|
10
|
+
|
|
11
|
+
/** @type {readonly CapabilityMethod[]} */
|
|
12
|
+
const LEGACY_METHOD_CAPABILITY_PREFIX = [
|
|
13
|
+
'access.request',
|
|
14
|
+
'tabs.list',
|
|
15
|
+
'tabs.create',
|
|
16
|
+
'tabs.close',
|
|
17
|
+
'tabs.activate',
|
|
18
|
+
'skill.get_runtime_context',
|
|
19
|
+
'setup.get_status',
|
|
20
|
+
'setup.install',
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
/** @type {readonly CapabilityMethod[]} */
|
|
24
|
+
const LEGACY_METHOD_CAPABILITY_SUFFIX = ['log.tail', 'health.ping', 'daemon.metrics'];
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
CAPABILITIES.DOM_READ,
|
|
32
|
-
CAPABILITIES.STYLES_READ,
|
|
33
|
-
CAPABILITIES.LAYOUT_READ,
|
|
34
|
-
CAPABILITIES.VIEWPORT_CONTROL,
|
|
35
|
-
CAPABILITIES.NAVIGATION_CONTROL,
|
|
36
|
-
CAPABILITIES.SCREENSHOT_PARTIAL,
|
|
37
|
-
CAPABILITIES.PATCH_DOM,
|
|
38
|
-
CAPABILITIES.PATCH_STYLES,
|
|
39
|
-
CAPABILITIES.AUTOMATION_INPUT,
|
|
40
|
-
CAPABILITIES.CDP_DOM_SNAPSHOT,
|
|
41
|
-
CAPABILITIES.CDP_BOX_MODEL,
|
|
42
|
-
CAPABILITIES.CDP_STYLES,
|
|
43
|
-
CAPABILITIES.CDP_INPUT,
|
|
44
|
-
CAPABILITIES.TABS_MANAGE,
|
|
45
|
-
CAPABILITIES.PERFORMANCE_READ,
|
|
46
|
-
CAPABILITIES.NETWORK_READ,
|
|
47
|
-
CAPABILITIES.NETWORK_INTERCEPT,
|
|
26
|
+
const LEGACY_POSITIONED_METHODS = new Set([
|
|
27
|
+
...LEGACY_METHOD_CAPABILITY_PREFIX,
|
|
28
|
+
...LEGACY_METHOD_CAPABILITY_SUFFIX,
|
|
48
29
|
]);
|
|
49
30
|
|
|
50
31
|
/** @type {Readonly<Record<CapabilityMethod, Capability | null>>} */
|
|
51
|
-
export const METHOD_CAPABILITIES = Object.freeze(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
'page.get_console': CAPABILITIES.PAGE_READ,
|
|
63
|
-
'page.wait_for_load_state': CAPABILITIES.PAGE_READ,
|
|
64
|
-
'page.get_storage': CAPABILITIES.PAGE_READ,
|
|
65
|
-
'page.get_text': CAPABILITIES.PAGE_READ,
|
|
66
|
-
'page.get_network': CAPABILITIES.NETWORK_READ,
|
|
67
|
-
// Interception mutates traffic (block/forge responses) - distinct from
|
|
68
|
-
// passive network reads so hosts can gate it independently.
|
|
69
|
-
'network.intercept.add': CAPABILITIES.NETWORK_INTERCEPT,
|
|
70
|
-
'network.intercept.remove': CAPABILITIES.NETWORK_INTERCEPT,
|
|
71
|
-
'network.intercept.list': CAPABILITIES.NETWORK_INTERCEPT,
|
|
72
|
-
'network.intercept.clear': CAPABILITIES.NETWORK_INTERCEPT,
|
|
73
|
-
'navigation.navigate': CAPABILITIES.NAVIGATION_CONTROL,
|
|
74
|
-
'navigation.reload': CAPABILITIES.NAVIGATION_CONTROL,
|
|
75
|
-
'navigation.go_back': CAPABILITIES.NAVIGATION_CONTROL,
|
|
76
|
-
'navigation.go_forward': CAPABILITIES.NAVIGATION_CONTROL,
|
|
77
|
-
'dom.query': CAPABILITIES.DOM_READ,
|
|
78
|
-
'dom.describe': CAPABILITIES.DOM_READ,
|
|
79
|
-
'dom.get_text': CAPABILITIES.DOM_READ,
|
|
80
|
-
'dom.get_attributes': CAPABILITIES.DOM_READ,
|
|
81
|
-
'dom.wait_for': CAPABILITIES.DOM_READ,
|
|
82
|
-
'dom.find_by_text': CAPABILITIES.DOM_READ,
|
|
83
|
-
'dom.find_by_role': CAPABILITIES.DOM_READ,
|
|
84
|
-
'dom.get_html': CAPABILITIES.DOM_READ,
|
|
85
|
-
'dom.get_accessibility_tree': CAPABILITIES.DOM_READ,
|
|
86
|
-
'layout.get_box_model': CAPABILITIES.LAYOUT_READ,
|
|
87
|
-
'layout.hit_test': CAPABILITIES.LAYOUT_READ,
|
|
88
|
-
'styles.get_computed': CAPABILITIES.STYLES_READ,
|
|
89
|
-
'styles.get_matched_rules': CAPABILITIES.STYLES_READ,
|
|
90
|
-
'viewport.scroll': CAPABILITIES.VIEWPORT_CONTROL,
|
|
91
|
-
'viewport.resize': CAPABILITIES.VIEWPORT_CONTROL,
|
|
92
|
-
'input.click': CAPABILITIES.AUTOMATION_INPUT,
|
|
93
|
-
'input.focus': CAPABILITIES.AUTOMATION_INPUT,
|
|
94
|
-
'input.type': CAPABILITIES.AUTOMATION_INPUT,
|
|
95
|
-
'input.fill': CAPABILITIES.AUTOMATION_INPUT,
|
|
96
|
-
'input.press_key': CAPABILITIES.AUTOMATION_INPUT,
|
|
97
|
-
'input.set_checked': CAPABILITIES.AUTOMATION_INPUT,
|
|
98
|
-
'input.select_option': CAPABILITIES.AUTOMATION_INPUT,
|
|
99
|
-
'input.hover': CAPABILITIES.AUTOMATION_INPUT,
|
|
100
|
-
'input.drag': CAPABILITIES.AUTOMATION_INPUT,
|
|
101
|
-
'input.scroll_into_view': CAPABILITIES.AUTOMATION_INPUT,
|
|
102
|
-
'screenshot.capture_region': CAPABILITIES.SCREENSHOT_PARTIAL,
|
|
103
|
-
'screenshot.capture_element': CAPABILITIES.SCREENSHOT_PARTIAL,
|
|
104
|
-
'screenshot.capture_full_page': CAPABILITIES.SCREENSHOT_PARTIAL,
|
|
105
|
-
'patch.apply_styles': CAPABILITIES.PATCH_STYLES,
|
|
106
|
-
'patch.apply_dom': CAPABILITIES.PATCH_DOM,
|
|
107
|
-
'patch.list': CAPABILITIES.PATCH_DOM,
|
|
108
|
-
'patch.rollback': CAPABILITIES.PATCH_DOM,
|
|
109
|
-
'patch.commit_session_baseline': CAPABILITIES.PATCH_DOM,
|
|
110
|
-
'cdp.get_document': CAPABILITIES.CDP_DOM_SNAPSHOT,
|
|
111
|
-
'cdp.get_dom_snapshot': CAPABILITIES.CDP_DOM_SNAPSHOT,
|
|
112
|
-
'cdp.get_box_model': CAPABILITIES.CDP_BOX_MODEL,
|
|
113
|
-
'cdp.get_computed_styles_for_node': CAPABILITIES.CDP_STYLES,
|
|
114
|
-
'cdp.dispatch_key_event': CAPABILITIES.CDP_INPUT,
|
|
115
|
-
'performance.get_metrics': CAPABILITIES.PERFORMANCE_READ,
|
|
116
|
-
'log.tail': null,
|
|
117
|
-
'health.ping': null,
|
|
118
|
-
'daemon.metrics': null,
|
|
119
|
-
});
|
|
32
|
+
export const METHOD_CAPABILITIES = Object.freeze(
|
|
33
|
+
/** @type {Record<CapabilityMethod, Capability | null>} */ (
|
|
34
|
+
Object.fromEntries(
|
|
35
|
+
[
|
|
36
|
+
...LEGACY_METHOD_CAPABILITY_PREFIX,
|
|
37
|
+
...BRIDGE_METHODS.filter((method) => !LEGACY_POSITIONED_METHODS.has(method)),
|
|
38
|
+
...LEGACY_METHOD_CAPABILITY_SUFFIX,
|
|
39
|
+
].map((method) => [method, BRIDGE_METHOD_REGISTRY[method].capability])
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
);
|
|
120
43
|
|
|
121
44
|
/**
|
|
122
45
|
* @param {unknown} value
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
export const CAPABILITIES = Object.freeze({
|
|
4
|
+
PAGE_READ: 'page.read',
|
|
5
|
+
PAGE_EVALUATE: 'page.evaluate',
|
|
6
|
+
DOM_READ: 'dom.read',
|
|
7
|
+
STYLES_READ: 'styles.read',
|
|
8
|
+
LAYOUT_READ: 'layout.read',
|
|
9
|
+
VIEWPORT_CONTROL: 'viewport.control',
|
|
10
|
+
NAVIGATION_CONTROL: 'navigation.control',
|
|
11
|
+
SCREENSHOT_PARTIAL: 'screenshot.partial',
|
|
12
|
+
PATCH_DOM: 'patch.dom',
|
|
13
|
+
PATCH_STYLES: 'patch.styles',
|
|
14
|
+
CDP_DOM_SNAPSHOT: 'cdp.dom_snapshot',
|
|
15
|
+
CDP_BOX_MODEL: 'cdp.box_model',
|
|
16
|
+
CDP_STYLES: 'cdp.styles',
|
|
17
|
+
CDP_INPUT: 'cdp.input',
|
|
18
|
+
AUTOMATION_INPUT: 'automation.input',
|
|
19
|
+
TABS_MANAGE: 'tabs.manage',
|
|
20
|
+
PERFORMANCE_READ: 'performance.read',
|
|
21
|
+
NETWORK_READ: 'network.read',
|
|
22
|
+
NETWORK_INTERCEPT: 'network.intercept',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const DEFAULT_CAPABILITIES = Object.freeze([
|
|
26
|
+
CAPABILITIES.PAGE_READ,
|
|
27
|
+
CAPABILITIES.PAGE_EVALUATE,
|
|
28
|
+
CAPABILITIES.DOM_READ,
|
|
29
|
+
CAPABILITIES.STYLES_READ,
|
|
30
|
+
CAPABILITIES.LAYOUT_READ,
|
|
31
|
+
CAPABILITIES.VIEWPORT_CONTROL,
|
|
32
|
+
CAPABILITIES.NAVIGATION_CONTROL,
|
|
33
|
+
CAPABILITIES.SCREENSHOT_PARTIAL,
|
|
34
|
+
CAPABILITIES.PATCH_DOM,
|
|
35
|
+
CAPABILITIES.PATCH_STYLES,
|
|
36
|
+
CAPABILITIES.AUTOMATION_INPUT,
|
|
37
|
+
CAPABILITIES.CDP_DOM_SNAPSHOT,
|
|
38
|
+
CAPABILITIES.CDP_BOX_MODEL,
|
|
39
|
+
CAPABILITIES.CDP_STYLES,
|
|
40
|
+
CAPABILITIES.CDP_INPUT,
|
|
41
|
+
CAPABILITIES.TABS_MANAGE,
|
|
42
|
+
CAPABILITIES.PERFORMANCE_READ,
|
|
43
|
+
CAPABILITIES.NETWORK_READ,
|
|
44
|
+
CAPABILITIES.NETWORK_INTERCEPT,
|
|
45
|
+
]);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
import { BRIDGE_METHODS, BRIDGE_METHOD_REGISTRY } from './registry.js';
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* Shared Browser Bridge defaults used by the protocol, MCP layer, and runtime
|
|
5
7
|
* guidance. Keep this as the source of truth for default limits and presets.
|
|
@@ -70,8 +72,8 @@ export const BUDGET_PRESETS = Object.freeze({
|
|
|
70
72
|
deep: { maxNodes: 100, maxDepth: 8, textBudget: 2000, tokenBudget: 4000 },
|
|
71
73
|
});
|
|
72
74
|
|
|
73
|
-
/** @type {
|
|
74
|
-
|
|
75
|
+
/** @type {readonly import('./types.js').BridgeMethod[]} */
|
|
76
|
+
const LEGACY_DEBUGGER_BACKED_METHOD_ORDER = [
|
|
75
77
|
'page.evaluate',
|
|
76
78
|
'dom.get_accessibility_tree',
|
|
77
79
|
'viewport.resize',
|
|
@@ -88,6 +90,19 @@ export const DEBUGGER_BACKED_METHODS = new Set([
|
|
|
88
90
|
'cdp.get_box_model',
|
|
89
91
|
'cdp.get_computed_styles_for_node',
|
|
90
92
|
'cdp.dispatch_key_event',
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
const LEGACY_DEBUGGER_BACKED_METHODS = new Set(LEGACY_DEBUGGER_BACKED_METHOD_ORDER);
|
|
96
|
+
|
|
97
|
+
/** @type {ReadonlySet<string>} */
|
|
98
|
+
export const DEBUGGER_BACKED_METHODS = new Set([
|
|
99
|
+
...LEGACY_DEBUGGER_BACKED_METHOD_ORDER.filter(
|
|
100
|
+
(method) => BRIDGE_METHOD_REGISTRY[method].debuggerBacked
|
|
101
|
+
),
|
|
102
|
+
...BRIDGE_METHODS.filter(
|
|
103
|
+
(method) =>
|
|
104
|
+
BRIDGE_METHOD_REGISTRY[method].debuggerBacked && !LEGACY_DEBUGGER_BACKED_METHODS.has(method)
|
|
105
|
+
),
|
|
91
106
|
]);
|
|
92
107
|
|
|
93
108
|
/**
|