@browserbridge/bbx 1.6.4 → 1.7.1
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 +1 -1
- package/packages/agent-client/src/cli.js +172 -34
- package/packages/agent-client/src/client.js +44 -7
- package/packages/agent-client/src/command-registry.js +5 -1
- package/packages/agent-client/src/remotes.js +28 -0
- package/packages/agent-client/src/runtime.js +230 -0
- package/packages/agent-client/src/types.ts +21 -0
- package/packages/mcp-server/src/handlers.js +2 -1
- package/packages/mcp-server/src/server.js +4 -1
- package/packages/native-host/bin/bridge-daemon.js +17 -2
- package/packages/native-host/bin/postinstall.js +18 -0
- package/packages/native-host/src/config.js +23 -0
- package/packages/native-host/src/daemon-process.js +138 -4
- package/packages/native-host/src/daemon.js +32 -9
- package/packages/native-host/src/native-host.js +1 -1
- package/packages/protocol/src/protocol.js +56 -7
- package/packages/protocol/src/summary.js +7 -2
- package/skills/browser-bridge/SKILL.md +15 -0
- package/skills/browser-bridge/references/protocol.md +1 -1
|
@@ -24,9 +24,10 @@ import {
|
|
|
24
24
|
DEFAULT_DAEMON_PENDING_TIMEOUT_MS,
|
|
25
25
|
DEFAULT_LOG_TAIL_LIMIT,
|
|
26
26
|
ERROR_CODES,
|
|
27
|
+
getProtocolVersion,
|
|
28
|
+
getSupportedProtocolVersions,
|
|
27
29
|
parseJsonLines,
|
|
28
|
-
|
|
29
|
-
SUPPORTED_VERSIONS,
|
|
30
|
+
setProtocolPackageVersion,
|
|
30
31
|
validateBridgeRequest,
|
|
31
32
|
} from '../../protocol/src/index.js';
|
|
32
33
|
import {
|
|
@@ -45,6 +46,7 @@ import { normalizeDaemonLogger } from './daemon-logger.js';
|
|
|
45
46
|
import { writeJsonLine } from './framing.js';
|
|
46
47
|
|
|
47
48
|
const DAEMON_VERSION = loadDaemonVersion();
|
|
49
|
+
setProtocolPackageVersion(DAEMON_VERSION);
|
|
48
50
|
|
|
49
51
|
/** @typedef {import('../../protocol/src/types.js').BridgeRequest} BridgeRequest */
|
|
50
52
|
/** @typedef {import('../../protocol/src/types.js').SetupInstallParams} SetupInstallParams */
|
|
@@ -89,14 +91,15 @@ function compareProtocolVersions(left, right) {
|
|
|
89
91
|
* @returns {{ supported_versions: readonly string[], deprecated_since?: string, migration_hint?: string }}
|
|
90
92
|
*/
|
|
91
93
|
function getVersionNegotiationPayload(requestedVersion) {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
94
|
+
const supportedVersions = getSupportedProtocolVersions();
|
|
95
|
+
const latestSupported = supportedVersions[0];
|
|
96
|
+
if (!requestedVersion || !latestSupported || supportedVersions.includes(requestedVersion)) {
|
|
97
|
+
return { supported_versions: supportedVersions };
|
|
95
98
|
}
|
|
96
99
|
|
|
97
100
|
const localIsNewer = compareProtocolVersions(latestSupported, requestedVersion) > 0;
|
|
98
101
|
return {
|
|
99
|
-
supported_versions:
|
|
102
|
+
supported_versions: supportedVersions,
|
|
100
103
|
...(localIsNewer ? { deprecated_since: latestSupported } : {}),
|
|
101
104
|
migration_hint: localIsNewer
|
|
102
105
|
? `Browser Bridge daemon is newer than the client protocol ${requestedVersion}. Restart or update the Browser Bridge CLI/npm package to ${latestSupported} or later.`
|
|
@@ -638,8 +641,9 @@ export class BridgeDaemon {
|
|
|
638
641
|
extensionConnected: false,
|
|
639
642
|
socketPath: this.socketPath,
|
|
640
643
|
transport: formatBridgeTransport(this.transport),
|
|
644
|
+
proxy: this.getProxyStatusPayload(),
|
|
641
645
|
connectedExtensions: [],
|
|
642
|
-
daemon_supported_versions:
|
|
646
|
+
daemon_supported_versions: getSupportedProtocolVersions(),
|
|
643
647
|
...getVersionNegotiationPayload(request.meta?.protocol_version),
|
|
644
648
|
});
|
|
645
649
|
await writeJsonLine(socket, { type: 'agent.response', response });
|
|
@@ -878,6 +882,24 @@ export class BridgeDaemon {
|
|
|
878
882
|
socket.__accessEnabled = accessEnabled;
|
|
879
883
|
}
|
|
880
884
|
|
|
885
|
+
/**
|
|
886
|
+
* Structured remote-exposure status for health payloads. The proxy counts
|
|
887
|
+
* as enabled only when the daemon listens on a TCP address other than
|
|
888
|
+
* loopback, i.e. agents on other machines can reach it.
|
|
889
|
+
*
|
|
890
|
+
* @returns {{ enabled: boolean, endpoint: string | null }}
|
|
891
|
+
*/
|
|
892
|
+
getProxyStatusPayload() {
|
|
893
|
+
if (this.transport.type !== 'tcp') {
|
|
894
|
+
return { enabled: false, endpoint: null };
|
|
895
|
+
}
|
|
896
|
+
const bindHost = this.transport.bindHost ?? this.transport.host;
|
|
897
|
+
const isLoopback = bindHost === '127.0.0.1' || bindHost === '::1' || bindHost === 'localhost';
|
|
898
|
+
return isLoopback
|
|
899
|
+
? { enabled: false, endpoint: null }
|
|
900
|
+
: { enabled: true, endpoint: `${bindHost}:${this.transport.port}` };
|
|
901
|
+
}
|
|
902
|
+
|
|
881
903
|
/**
|
|
882
904
|
* @param {ClientSocket} socket
|
|
883
905
|
* @param {DaemonMessage} message
|
|
@@ -929,7 +951,8 @@ export class BridgeDaemon {
|
|
|
929
951
|
...getVersionNegotiationPayload(pending.protocolVersion),
|
|
930
952
|
.../** @type {Record<string, unknown>} */ (responseMessage.result),
|
|
931
953
|
daemonVersion: DAEMON_VERSION,
|
|
932
|
-
daemon_supported_versions:
|
|
954
|
+
daemon_supported_versions: getSupportedProtocolVersions(),
|
|
955
|
+
proxy: this.getProxyStatusPayload(),
|
|
933
956
|
},
|
|
934
957
|
{
|
|
935
958
|
...responseMessage.meta,
|
|
@@ -1141,7 +1164,7 @@ export async function pingExistingDaemon(transport) {
|
|
|
1141
1164
|
method: 'health.ping',
|
|
1142
1165
|
tab_id: null,
|
|
1143
1166
|
params: {},
|
|
1144
|
-
meta: { protocol_version:
|
|
1167
|
+
meta: { protocol_version: getProtocolVersion(), token_budget: null },
|
|
1145
1168
|
},
|
|
1146
1169
|
})}\n`
|
|
1147
1170
|
);
|
|
@@ -125,7 +125,7 @@ export async function runNativeHost({
|
|
|
125
125
|
socket = await connectWithBootstrap(resolvedTransport);
|
|
126
126
|
} catch (error) {
|
|
127
127
|
await writeNativeMessageQueued({
|
|
128
|
-
type: '
|
|
128
|
+
type: 'host.bridge_response',
|
|
129
129
|
response: createFailure(
|
|
130
130
|
'native_bootstrap',
|
|
131
131
|
ERROR_CODES.NATIVE_HOST_UNAVAILABLE,
|
|
@@ -82,10 +82,59 @@ import { BRIDGE_METHODS, METHOD_SET, createBridgeMethodGroups } from './registry
|
|
|
82
82
|
/** @typedef {import('./types.js').WaitForLoadStateParams} WaitForLoadStateParams */
|
|
83
83
|
/** @typedef {import('./types.js').WaitForParams} WaitForParams */
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
/** @type {string | null} */
|
|
86
|
+
let protocolPackageVersion = null;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @param {string | null | undefined} packageVersion
|
|
90
|
+
* @returns {string}
|
|
91
|
+
*/
|
|
92
|
+
export function deriveProtocolVersion(packageVersion) {
|
|
93
|
+
const match = typeof packageVersion === 'string' ? /^(\d+)\.(\d+)/.exec(packageVersion) : null;
|
|
94
|
+
return match ? `${match[1]}.${match[2]}` : '0.0';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @returns {string | null}
|
|
99
|
+
*/
|
|
100
|
+
function getRuntimePackageVersion() {
|
|
101
|
+
const chromeRuntime = /** @type {{ runtime?: { getManifest?: () => { version?: unknown } } }} */ (
|
|
102
|
+
globalThis.chrome ?? {}
|
|
103
|
+
).runtime;
|
|
104
|
+
const manifestVersion = chromeRuntime?.getManifest?.().version;
|
|
105
|
+
if (typeof manifestVersion === 'string') {
|
|
106
|
+
return manifestVersion;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const npmPackageVersion = globalThis.process?.env?.npm_package_version;
|
|
110
|
+
return typeof npmPackageVersion === 'string' ? npmPackageVersion : null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* @param {string | null | undefined} packageVersion
|
|
115
|
+
* @returns {void}
|
|
116
|
+
*/
|
|
117
|
+
export function setProtocolPackageVersion(packageVersion) {
|
|
118
|
+
protocolPackageVersion = typeof packageVersion === 'string' ? packageVersion : null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* @returns {string}
|
|
123
|
+
*/
|
|
124
|
+
export function getProtocolVersion() {
|
|
125
|
+
return deriveProtocolVersion(protocolPackageVersion ?? getRuntimePackageVersion());
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Snapshot retained for older callers; new code should call getProtocolVersion(). */
|
|
129
|
+
export const PROTOCOL_VERSION = getProtocolVersion();
|
|
86
130
|
|
|
87
131
|
/** Versions this build can speak. Newest first. */
|
|
88
|
-
export
|
|
132
|
+
export function getSupportedProtocolVersions() {
|
|
133
|
+
return Object.freeze([getProtocolVersion()]);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Snapshot retained for older callers; new code should call getSupportedProtocolVersions(). */
|
|
137
|
+
export const SUPPORTED_VERSIONS = getSupportedProtocolVersions();
|
|
89
138
|
|
|
90
139
|
/**
|
|
91
140
|
* Clamp a numeric value between min and max, falling back to a default.
|
|
@@ -122,7 +171,7 @@ export function createRequest({ id, method, tabId = null, params = {}, meta = {}
|
|
|
122
171
|
tab_id: tabId,
|
|
123
172
|
params,
|
|
124
173
|
meta: {
|
|
125
|
-
protocol_version:
|
|
174
|
+
protocol_version: getProtocolVersion(),
|
|
126
175
|
...meta,
|
|
127
176
|
},
|
|
128
177
|
});
|
|
@@ -141,7 +190,7 @@ export function createSuccess(id, result, meta = {}) {
|
|
|
141
190
|
result,
|
|
142
191
|
error: null,
|
|
143
192
|
meta: {
|
|
144
|
-
protocol_version:
|
|
193
|
+
protocol_version: getProtocolVersion(),
|
|
145
194
|
...meta,
|
|
146
195
|
},
|
|
147
196
|
};
|
|
@@ -168,7 +217,7 @@ export function createFailure(id, code, message, details = null, meta = {}) {
|
|
|
168
217
|
...(recovery && { recovery }),
|
|
169
218
|
},
|
|
170
219
|
meta: {
|
|
171
|
-
protocol_version:
|
|
220
|
+
protocol_version: getProtocolVersion(),
|
|
172
221
|
...meta,
|
|
173
222
|
},
|
|
174
223
|
};
|
|
@@ -238,7 +287,7 @@ export function validateBridgeRequest(request) {
|
|
|
238
287
|
meta: {
|
|
239
288
|
...meta,
|
|
240
289
|
protocol_version:
|
|
241
|
-
typeof meta.protocol_version === 'string' ? meta.protocol_version :
|
|
290
|
+
typeof meta.protocol_version === 'string' ? meta.protocol_version : getProtocolVersion(),
|
|
242
291
|
token_budget: typeof meta.token_budget === 'number' ? meta.token_budget : null,
|
|
243
292
|
source: meta.source === 'cli' || meta.source === 'mcp' ? meta.source : undefined,
|
|
244
293
|
},
|
|
@@ -842,7 +891,7 @@ export function createRuntimeContext() {
|
|
|
842
891
|
const methodGroups = createBridgeMethodGroups();
|
|
843
892
|
|
|
844
893
|
return {
|
|
845
|
-
v:
|
|
894
|
+
v: getProtocolVersion(),
|
|
846
895
|
budgets: {
|
|
847
896
|
quick: {
|
|
848
897
|
n: BUDGET_PRESETS.quick.maxNodes,
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
estimateSerializedPayloadCost,
|
|
5
|
+
getCostClass,
|
|
6
|
+
getProtocolVersion,
|
|
7
|
+
serializeJsonPayload,
|
|
8
|
+
} from './index.js';
|
|
4
9
|
|
|
5
10
|
/** @typedef {import('./types.js').BridgeResponse} BridgeResponse */
|
|
6
11
|
/** @typedef {import('./types.js').BridgeMethod} SummaryMethod */
|
|
@@ -692,7 +697,7 @@ export function summarizeBatchErrorItem({ method, tabId, error, durationMs }) {
|
|
|
692
697
|
message,
|
|
693
698
|
details: null,
|
|
694
699
|
},
|
|
695
|
-
meta: { protocol_version:
|
|
700
|
+
meta: { protocol_version: getProtocolVersion() },
|
|
696
701
|
});
|
|
697
702
|
const summary = annotateBridgeSummary(summarizeBridgeResponse(response, method), response);
|
|
698
703
|
return {
|
|
@@ -34,6 +34,8 @@ bbx tab-activate <tabId> # bring a tab to the foreground
|
|
|
34
34
|
bbx skill # live runtime presets + limits
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
Use the globally installed `bbx` command or `node packages/agent-client/src/cli.js ...` for live readiness checks from this repository. Avoid `rtk npm exec -- bbx status` as a health signal: that path can restart/replace the daemon and report `Extension: disconnected` before Chrome reconnects. If it happens, wait a few seconds and verify with `bbx status`.
|
|
38
|
+
|
|
37
39
|
### Inspect & Find
|
|
38
40
|
|
|
39
41
|
```bash
|
|
@@ -89,6 +91,19 @@ bbx screenshot <ref> [outPath] # capture partial element screenshot
|
|
|
89
91
|
bbx call screenshot.capture_full_page '{}' # raw base64; avoid unless document context matters
|
|
90
92
|
```
|
|
91
93
|
|
|
94
|
+
### Remote Destinations
|
|
95
|
+
|
|
96
|
+
Every bridge command accepts `--remote <name>` (or `BBX_REMOTE=<name>` env) to target a browser on another machine registered with `bbx remote add`:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
bbx remote list # configured remote destinations
|
|
100
|
+
bbx remote test <name> # ping a remote through the proxy
|
|
101
|
+
bbx tabs --remote <name> # any bridge command works with --remote
|
|
102
|
+
bbx dom-query "#app" --remote <name>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
In MCP mode, pass `destinationId` on any browser tool call instead; `browser_status` lists all destinations with reachability. Only use remotes the user has configured; local remains the default.
|
|
106
|
+
|
|
92
107
|
## Access Flow
|
|
93
108
|
|
|
94
109
|
Browser Bridge access is window-scoped. The user turns it on once for the current browser window in the popup or side panel.
|
|
@@ -348,7 +348,7 @@ bbx call screenshot.capture_full_page '{}'
|
|
|
348
348
|
"tab_id": 123,
|
|
349
349
|
"method": "dom.query",
|
|
350
350
|
"params": {},
|
|
351
|
-
"meta": { "protocol_version": "
|
|
351
|
+
"meta": { "protocol_version": "<package major.minor>", "token_budget": 1200 }
|
|
352
352
|
}
|
|
353
353
|
```
|
|
354
354
|
|