@browserbridge/bbx 1.0.0 → 1.1.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 +6 -4
- package/package.json +53 -53
- package/packages/agent-client/src/cli-helpers.js +43 -5
- package/packages/agent-client/src/cli.js +176 -171
- package/packages/agent-client/src/client.js +66 -21
- package/packages/agent-client/src/command-registry.js +104 -69
- package/packages/agent-client/src/detect.js +162 -54
- package/packages/agent-client/src/install.js +34 -28
- package/packages/agent-client/src/mcp-config.js +40 -40
- package/packages/agent-client/src/runtime.js +41 -20
- package/packages/agent-client/src/setup-status.js +23 -30
- package/packages/mcp-server/src/bin.js +57 -5
- package/packages/mcp-server/src/handlers.js +573 -256
- package/packages/mcp-server/src/server.js +568 -257
- package/packages/native-host/bin/bridge-daemon.js +39 -6
- package/packages/native-host/bin/install-manifest.js +26 -4
- package/packages/native-host/bin/postinstall.js +4 -2
- package/packages/native-host/src/config.js +142 -13
- package/packages/native-host/src/daemon-process.js +396 -0
- package/packages/native-host/src/daemon.js +350 -150
- package/packages/native-host/src/framing.js +131 -11
- package/packages/native-host/src/install-manifest.js +194 -29
- package/packages/native-host/src/native-host.js +154 -102
- package/packages/protocol/src/budget.js +3 -7
- package/packages/protocol/src/capabilities.js +6 -3
- package/packages/protocol/src/defaults.js +1 -0
- package/packages/protocol/src/errors.js +15 -11
- package/packages/protocol/src/payload-cost.js +19 -6
- package/packages/protocol/src/protocol.js +242 -73
- package/packages/protocol/src/registry.js +311 -45
- package/packages/protocol/src/summary.js +260 -109
- package/packages/protocol/src/types.js +29 -4
- package/skills/browser-bridge/SKILL.md +3 -2
- package/skills/browser-bridge/agents/openai.yaml +3 -3
- package/skills/browser-bridge/references/interaction.md +34 -11
- package/skills/browser-bridge/references/patch-workflow.md +3 -0
- package/skills/browser-bridge/references/protocol.md +127 -71
- package/skills/browser-bridge/references/tailwind.md +12 -11
- package/skills/browser-bridge/references/token-efficiency.md +23 -22
- package/skills/browser-bridge/references/ui-workflows.md +8 -0
- package/CHANGELOG.md +0 -55
- package/assets/banner.jpg +0 -0
- package/assets/logo.png +0 -0
- package/assets/logo.svg +0 -65
- package/docs/api-reference.md +0 -157
- package/docs/cli-guide.md +0 -128
- package/docs/index.md +0 -25
- package/docs/manual-setup.md +0 -140
- package/docs/mcp-vs-cli.md +0 -258
- package/docs/publishing.md +0 -114
- package/docs/quickstart.md +0 -104
- package/docs/troubleshooting.md +0 -59
- package/docs/usage-scenarios.md +0 -136
- package/manifest.json +0 -52
- package/packages/extension/assets/icon-128.png +0 -0
- package/packages/extension/assets/icon-16.png +0 -0
- package/packages/extension/assets/icon-32.png +0 -0
- package/packages/extension/assets/icon-48.png +0 -0
- package/packages/extension/src/background-helpers.js +0 -459
- package/packages/extension/src/background-routing.js +0 -91
- package/packages/extension/src/background.js +0 -3227
- package/packages/extension/src/content-script-helpers.js +0 -281
- package/packages/extension/src/content-script.js +0 -1977
- package/packages/extension/src/debugger-coordinator.js +0 -188
- package/packages/extension/src/sidepanel-helpers.js +0 -102
- package/packages/extension/ui/offscreen.html +0 -6
- package/packages/extension/ui/offscreen.js +0 -61
- package/packages/extension/ui/popup.html +0 -35
- package/packages/extension/ui/popup.js +0 -279
- package/packages/extension/ui/sidepanel.html +0 -102
- package/packages/extension/ui/sidepanel.js +0 -1854
- package/packages/extension/ui/ui.css +0 -1159
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
DEFAULT_WAIT_TIMEOUT_MS,
|
|
20
20
|
} from './defaults.js';
|
|
21
21
|
import { BridgeError, ERROR_CODES, getErrorRecovery } from './errors.js';
|
|
22
|
-
import { BRIDGE_METHODS, createBridgeMethodGroups } from './registry.js';
|
|
22
|
+
import { BRIDGE_METHODS, METHOD_SET, createBridgeMethodGroups } from './registry.js';
|
|
23
23
|
|
|
24
24
|
/** @typedef {import('./types.js').AccessibilityTreeParams} AccessibilityTreeParams */
|
|
25
25
|
/** @typedef {import('./types.js').BridgeFailureResponse} BridgeFailureResponse */
|
|
@@ -28,6 +28,7 @@ import { BRIDGE_METHODS, createBridgeMethodGroups } from './registry.js';
|
|
|
28
28
|
/** @typedef {import('./types.js').BridgeRequest} BridgeRequest */
|
|
29
29
|
/** @typedef {import('./types.js').BridgeSuccessResponse} BridgeSuccessResponse */
|
|
30
30
|
/** @typedef {import('./types.js').CheckedActionParams} CheckedActionParams */
|
|
31
|
+
/** @typedef {import('./types.js').CdpDispatchKeyEventParams} CdpDispatchKeyEventParams */
|
|
31
32
|
/** @typedef {import('./types.js').ConsoleParams} ConsoleParams */
|
|
32
33
|
/** @typedef {import('./types.js').DomQueryParams} DomQueryParams */
|
|
33
34
|
/** @typedef {import('./types.js').DragParams} DragParams */
|
|
@@ -41,6 +42,7 @@ import { BRIDGE_METHODS, createBridgeMethodGroups } from './registry.js';
|
|
|
41
42
|
/** @typedef {import('./types.js').NetworkParams} NetworkParams */
|
|
42
43
|
/** @typedef {import('./types.js').NormalizedAccessibilityTreeParams} NormalizedAccessibilityTreeParams */
|
|
43
44
|
/** @typedef {import('./types.js').NormalizedCheckedAction} NormalizedCheckedAction */
|
|
45
|
+
/** @typedef {import('./types.js').NormalizedCdpDispatchKeyEventParams} NormalizedCdpDispatchKeyEventParams */
|
|
44
46
|
/** @typedef {import('./types.js').NormalizedConsoleParams} NormalizedConsoleParams */
|
|
45
47
|
/** @typedef {import('./types.js').NormalizedDomQuery} NormalizedDomQuery */
|
|
46
48
|
/** @typedef {import('./types.js').NormalizedDragParams} NormalizedDragParams */
|
|
@@ -114,8 +116,8 @@ export function createRequest({ id, method, tabId = null, params = {}, meta = {}
|
|
|
114
116
|
params,
|
|
115
117
|
meta: {
|
|
116
118
|
protocol_version: PROTOCOL_VERSION,
|
|
117
|
-
...meta
|
|
118
|
-
}
|
|
119
|
+
...meta,
|
|
120
|
+
},
|
|
119
121
|
});
|
|
120
122
|
}
|
|
121
123
|
|
|
@@ -133,8 +135,8 @@ export function createSuccess(id, result, meta = {}) {
|
|
|
133
135
|
error: null,
|
|
134
136
|
meta: {
|
|
135
137
|
protocol_version: PROTOCOL_VERSION,
|
|
136
|
-
...meta
|
|
137
|
-
}
|
|
138
|
+
...meta,
|
|
139
|
+
},
|
|
138
140
|
};
|
|
139
141
|
}
|
|
140
142
|
|
|
@@ -156,12 +158,12 @@ export function createFailure(id, code, message, details = null, meta = {}) {
|
|
|
156
158
|
code,
|
|
157
159
|
message,
|
|
158
160
|
details,
|
|
159
|
-
...(recovery && { recovery })
|
|
161
|
+
...(recovery && { recovery }),
|
|
160
162
|
},
|
|
161
163
|
meta: {
|
|
162
164
|
protocol_version: PROTOCOL_VERSION,
|
|
163
|
-
...meta
|
|
164
|
-
}
|
|
165
|
+
...meta,
|
|
166
|
+
},
|
|
165
167
|
};
|
|
166
168
|
}
|
|
167
169
|
|
|
@@ -180,45 +182,142 @@ export function validateBridgeRequest(request) {
|
|
|
180
182
|
throw new BridgeError(ERROR_CODES.INVALID_REQUEST, 'Request id must be a non-empty string.');
|
|
181
183
|
}
|
|
182
184
|
|
|
183
|
-
if (
|
|
184
|
-
|
|
185
|
+
if (
|
|
186
|
+
typeof candidate.method !== 'string' ||
|
|
187
|
+
!METHOD_SET.has(/** @type {BridgeMethod} */ (candidate.method))
|
|
188
|
+
) {
|
|
189
|
+
throw new BridgeError(
|
|
190
|
+
ERROR_CODES.INVALID_REQUEST,
|
|
191
|
+
`Unsupported method: ${String(candidate.method)}`
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (
|
|
196
|
+
candidate.meta != null &&
|
|
197
|
+
(typeof candidate.meta !== 'object' || Array.isArray(candidate.meta))
|
|
198
|
+
) {
|
|
199
|
+
throw new BridgeError(ERROR_CODES.INVALID_REQUEST, 'Request meta must be an object.');
|
|
185
200
|
}
|
|
186
201
|
|
|
187
|
-
const meta =
|
|
188
|
-
|
|
189
|
-
|
|
202
|
+
const meta =
|
|
203
|
+
candidate.meta && typeof candidate.meta === 'object'
|
|
204
|
+
? /** @type {Record<string, unknown>} */ (candidate.meta)
|
|
205
|
+
: {};
|
|
190
206
|
if (candidate.session_id != null) {
|
|
191
|
-
throw new BridgeError(
|
|
207
|
+
throw new BridgeError(
|
|
208
|
+
ERROR_CODES.INVALID_REQUEST,
|
|
209
|
+
'session_id is no longer supported. Use tab_id or window-scoped default routing.'
|
|
210
|
+
);
|
|
192
211
|
}
|
|
193
212
|
const parsedTabId = Number(candidate.tab_id);
|
|
194
213
|
|
|
214
|
+
const method = /** @type {BridgeMethod} */ (candidate.method);
|
|
215
|
+
const params =
|
|
216
|
+
candidate.params && typeof candidate.params === 'object'
|
|
217
|
+
? /** @type {Record<string, unknown>} */ (candidate.params)
|
|
218
|
+
: {};
|
|
219
|
+
|
|
195
220
|
return {
|
|
196
221
|
id: candidate.id,
|
|
197
|
-
method
|
|
222
|
+
method,
|
|
198
223
|
tab_id: Number.isFinite(parsedTabId) && parsedTabId > 0 ? parsedTabId : null,
|
|
199
|
-
params:
|
|
200
|
-
? /** @type {Record<string, unknown>} */ (candidate.params)
|
|
201
|
-
: {},
|
|
224
|
+
params: normalizeRequestParams(method, params),
|
|
202
225
|
meta: {
|
|
203
226
|
...meta,
|
|
204
|
-
protocol_version:
|
|
205
|
-
? meta.protocol_version
|
|
206
|
-
: PROTOCOL_VERSION,
|
|
227
|
+
protocol_version:
|
|
228
|
+
typeof meta.protocol_version === 'string' ? meta.protocol_version : PROTOCOL_VERSION,
|
|
207
229
|
token_budget: typeof meta.token_budget === 'number' ? meta.token_budget : null,
|
|
208
|
-
source: meta.source === 'cli' || meta.source === 'mcp' ? meta.source : undefined
|
|
209
|
-
}
|
|
230
|
+
source: meta.source === 'cli' || meta.source === 'mcp' ? meta.source : undefined,
|
|
231
|
+
},
|
|
210
232
|
};
|
|
211
233
|
}
|
|
212
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Normalize request params early so malformed payloads fail at the shared
|
|
237
|
+
* protocol boundary before daemon or extension dispatch.
|
|
238
|
+
*
|
|
239
|
+
* @param {BridgeMethod} method
|
|
240
|
+
* @param {Record<string, unknown>} params
|
|
241
|
+
* @returns {Record<string, unknown>}
|
|
242
|
+
*/
|
|
243
|
+
function normalizeRequestParams(method, params) {
|
|
244
|
+
switch (method) {
|
|
245
|
+
case 'dom.query':
|
|
246
|
+
return normalizeDomQuery(params);
|
|
247
|
+
case 'page.evaluate':
|
|
248
|
+
return normalizeEvaluateParams(params);
|
|
249
|
+
case 'page.get_console':
|
|
250
|
+
return normalizeConsoleParams(params);
|
|
251
|
+
case 'page.wait_for_load_state':
|
|
252
|
+
return normalizeWaitForLoadStateParams(params);
|
|
253
|
+
case 'page.get_storage':
|
|
254
|
+
return normalizeStorageParams(params);
|
|
255
|
+
case 'page.get_text':
|
|
256
|
+
return normalizePageTextParams(params);
|
|
257
|
+
case 'page.get_network':
|
|
258
|
+
return normalizeNetworkParams(params);
|
|
259
|
+
case 'navigation.navigate':
|
|
260
|
+
case 'navigation.reload':
|
|
261
|
+
case 'navigation.go_back':
|
|
262
|
+
case 'navigation.go_forward':
|
|
263
|
+
return normalizeNavigationAction(params);
|
|
264
|
+
case 'dom.wait_for':
|
|
265
|
+
return normalizeWaitForParams(params);
|
|
266
|
+
case 'dom.find_by_text':
|
|
267
|
+
return normalizeFindByTextParams(params);
|
|
268
|
+
case 'dom.find_by_role':
|
|
269
|
+
return normalizeFindByRoleParams(params);
|
|
270
|
+
case 'dom.get_html':
|
|
271
|
+
return normalizeGetHtmlParams(params);
|
|
272
|
+
case 'dom.get_accessibility_tree':
|
|
273
|
+
return normalizeAccessibilityTreeParams(params);
|
|
274
|
+
case 'styles.get_computed':
|
|
275
|
+
case 'styles.get_matched_rules':
|
|
276
|
+
return normalizeStyleQuery(params);
|
|
277
|
+
case 'viewport.scroll':
|
|
278
|
+
return normalizeViewportAction(params);
|
|
279
|
+
case 'viewport.resize':
|
|
280
|
+
return normalizeViewportResizeParams(params);
|
|
281
|
+
case 'input.click':
|
|
282
|
+
case 'input.focus':
|
|
283
|
+
case 'input.type':
|
|
284
|
+
case 'input.press_key':
|
|
285
|
+
return normalizeInputAction(params);
|
|
286
|
+
case 'cdp.dispatch_key_event':
|
|
287
|
+
return normalizeCdpDispatchKeyEventParams(params);
|
|
288
|
+
case 'input.set_checked':
|
|
289
|
+
return normalizeCheckedAction(params);
|
|
290
|
+
case 'input.select_option':
|
|
291
|
+
return normalizeSelectAction(params);
|
|
292
|
+
case 'input.hover':
|
|
293
|
+
return normalizeHoverParams(params);
|
|
294
|
+
case 'input.drag':
|
|
295
|
+
return normalizeDragParams(params);
|
|
296
|
+
case 'patch.apply_styles':
|
|
297
|
+
case 'patch.apply_dom':
|
|
298
|
+
case 'patch.list':
|
|
299
|
+
case 'patch.rollback':
|
|
300
|
+
case 'patch.commit_session_baseline':
|
|
301
|
+
return normalizePatchOperation(params);
|
|
302
|
+
case 'tabs.create':
|
|
303
|
+
return normalizeTabCreateParams(params);
|
|
304
|
+
case 'tabs.close':
|
|
305
|
+
return normalizeTabCloseParams(params);
|
|
306
|
+
default:
|
|
307
|
+
return params;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
213
311
|
/**
|
|
214
312
|
* @param {DomQueryParams} [params={}]
|
|
215
313
|
* @returns {NormalizedDomQuery}
|
|
216
314
|
*/
|
|
217
315
|
export function normalizeDomQuery(params = {}) {
|
|
218
316
|
return {
|
|
219
|
-
selector:
|
|
317
|
+
selector:
|
|
318
|
+
typeof params.selector === 'string' && params.selector.trim() ? params.selector : 'body',
|
|
220
319
|
withinRef: typeof params.withinRef === 'string' ? params.withinRef : null,
|
|
221
|
-
budget: applyBudget(params)
|
|
320
|
+
budget: applyBudget(params),
|
|
222
321
|
};
|
|
223
322
|
}
|
|
224
323
|
|
|
@@ -234,12 +333,15 @@ export function normalizeStyleQuery(params = {}) {
|
|
|
234
333
|
);
|
|
235
334
|
const elementRef = String(params.elementRef || target.elementRef || '');
|
|
236
335
|
if (!elementRef && !target.selector) {
|
|
237
|
-
throw new BridgeError(
|
|
336
|
+
throw new BridgeError(
|
|
337
|
+
ERROR_CODES.INVALID_REQUEST,
|
|
338
|
+
'elementRef or target is required for style queries.'
|
|
339
|
+
);
|
|
238
340
|
}
|
|
239
341
|
return {
|
|
240
342
|
elementRef,
|
|
241
343
|
target,
|
|
242
|
-
properties: Array.isArray(params.properties) ? params.properties.filter(Boolean) : []
|
|
344
|
+
properties: Array.isArray(params.properties) ? params.properties.filter(Boolean) : [],
|
|
243
345
|
};
|
|
244
346
|
}
|
|
245
347
|
|
|
@@ -250,7 +352,7 @@ export function normalizeStyleQuery(params = {}) {
|
|
|
250
352
|
function normalizeTarget(target) {
|
|
251
353
|
return {
|
|
252
354
|
elementRef: typeof target?.elementRef === 'string' ? target.elementRef : undefined,
|
|
253
|
-
selector: typeof target?.selector === 'string' ? target.selector : undefined
|
|
355
|
+
selector: typeof target?.selector === 'string' ? target.selector : undefined,
|
|
254
356
|
};
|
|
255
357
|
}
|
|
256
358
|
|
|
@@ -259,9 +361,7 @@ function normalizeTarget(target) {
|
|
|
259
361
|
* @returns {NormalizedInputAction}
|
|
260
362
|
*/
|
|
261
363
|
export function normalizeInputAction(params = {}) {
|
|
262
|
-
const button = params.button === 'middle' || params.button === 'right'
|
|
263
|
-
? params.button
|
|
264
|
-
: 'left';
|
|
364
|
+
const button = params.button === 'middle' || params.button === 'right' ? params.button : 'left';
|
|
265
365
|
|
|
266
366
|
return {
|
|
267
367
|
target: normalizeTarget(
|
|
@@ -277,7 +377,55 @@ export function normalizeInputAction(params = {}) {
|
|
|
277
377
|
key: typeof params.key === 'string' ? params.key : '',
|
|
278
378
|
modifiers: Array.isArray(params.modifiers)
|
|
279
379
|
? params.modifiers.filter((modifier) => typeof modifier === 'string' && modifier.trim())
|
|
280
|
-
: []
|
|
380
|
+
: [],
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* @param {CdpDispatchKeyEventParams} [params={}]
|
|
386
|
+
* @returns {NormalizedCdpDispatchKeyEventParams}
|
|
387
|
+
*/
|
|
388
|
+
export function normalizeCdpDispatchKeyEventParams(params = {}) {
|
|
389
|
+
if (typeof params.key !== 'string' || !params.key.trim()) {
|
|
390
|
+
throw new BridgeError(ERROR_CODES.INVALID_REQUEST, 'key must be a non-empty string.');
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (
|
|
394
|
+
params.modifiers != null &&
|
|
395
|
+
typeof params.modifiers !== 'number' &&
|
|
396
|
+
!Array.isArray(params.modifiers)
|
|
397
|
+
) {
|
|
398
|
+
throw new BridgeError(
|
|
399
|
+
ERROR_CODES.INVALID_REQUEST,
|
|
400
|
+
'modifiers must be an array of Alt, Control, Meta, Shift or a bitmask 0-15.'
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (
|
|
405
|
+
typeof params.modifiers === 'number' &&
|
|
406
|
+
(!Number.isInteger(params.modifiers) || params.modifiers < 0 || params.modifiers > 15)
|
|
407
|
+
) {
|
|
408
|
+
throw new BridgeError(
|
|
409
|
+
ERROR_CODES.INVALID_REQUEST,
|
|
410
|
+
'modifiers must be an array of Alt, Control, Meta, Shift or a bitmask 0-15.'
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (Array.isArray(params.modifiers)) {
|
|
415
|
+
for (const modifier of params.modifiers) {
|
|
416
|
+
if (typeof modifier !== 'string' || !['Alt', 'Control', 'Meta', 'Shift'].includes(modifier)) {
|
|
417
|
+
throw new BridgeError(
|
|
418
|
+
ERROR_CODES.INVALID_REQUEST,
|
|
419
|
+
'modifiers must contain only Alt, Control, Meta, or Shift.'
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return {
|
|
426
|
+
key: params.key,
|
|
427
|
+
code: typeof params.code === 'string' ? params.code.trim() : '',
|
|
428
|
+
modifiers: params.modifiers ?? [],
|
|
281
429
|
};
|
|
282
430
|
}
|
|
283
431
|
|
|
@@ -292,7 +440,7 @@ export function normalizeCheckedAction(params = {}) {
|
|
|
292
440
|
? /** @type {{ elementRef?: string, selector?: string }} */ (params.target)
|
|
293
441
|
: undefined
|
|
294
442
|
),
|
|
295
|
-
checked: params.checked !== false
|
|
443
|
+
checked: params.checked !== false,
|
|
296
444
|
};
|
|
297
445
|
}
|
|
298
446
|
|
|
@@ -315,9 +463,9 @@ export function normalizeSelectAction(params = {}) {
|
|
|
315
463
|
: [],
|
|
316
464
|
indexes: Array.isArray(params.indexes)
|
|
317
465
|
? params.indexes
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
: []
|
|
466
|
+
.map((index) => Number(index))
|
|
467
|
+
.filter((index) => Number.isInteger(index) && index >= 0)
|
|
468
|
+
: [],
|
|
321
469
|
};
|
|
322
470
|
}
|
|
323
471
|
|
|
@@ -335,7 +483,7 @@ export function normalizeViewportAction(params = {}) {
|
|
|
335
483
|
top: Number.isFinite(Number(params.top)) ? Number(params.top) : 0,
|
|
336
484
|
left: Number.isFinite(Number(params.left)) ? Number(params.left) : 0,
|
|
337
485
|
behavior: params.behavior === 'smooth' ? 'smooth' : 'auto',
|
|
338
|
-
relative: Boolean(params.relative)
|
|
486
|
+
relative: Boolean(params.relative),
|
|
339
487
|
};
|
|
340
488
|
}
|
|
341
489
|
|
|
@@ -362,7 +510,7 @@ export function normalizeNavigationAction(params = {}) {
|
|
|
362
510
|
return {
|
|
363
511
|
url,
|
|
364
512
|
waitForLoad: params.waitForLoad !== false,
|
|
365
|
-
timeoutMs: clampInt(params.timeoutMs, 500, 120_000, 15_000)
|
|
513
|
+
timeoutMs: clampInt(params.timeoutMs, 500, 120_000, 15_000),
|
|
366
514
|
};
|
|
367
515
|
}
|
|
368
516
|
|
|
@@ -373,17 +521,19 @@ export function normalizeNavigationAction(params = {}) {
|
|
|
373
521
|
export function normalizePatchOperation(params = {}) {
|
|
374
522
|
return {
|
|
375
523
|
patchId: typeof params.patchId === 'string' ? params.patchId : null,
|
|
376
|
-
target:
|
|
377
|
-
|
|
378
|
-
|
|
524
|
+
target:
|
|
525
|
+
params.target && typeof params.target === 'object'
|
|
526
|
+
? /** @type {Record<string, unknown>} */ (params.target)
|
|
527
|
+
: {},
|
|
379
528
|
operation: typeof params.operation === 'string' ? params.operation : null,
|
|
380
529
|
name: typeof params.name === 'string' ? params.name : null,
|
|
381
|
-
declarations:
|
|
382
|
-
|
|
383
|
-
|
|
530
|
+
declarations:
|
|
531
|
+
params.declarations && typeof params.declarations === 'object'
|
|
532
|
+
? /** @type {Record<string, string>} */ (params.declarations)
|
|
533
|
+
: {},
|
|
384
534
|
value: params.value ?? null,
|
|
385
535
|
important: Boolean(params.important),
|
|
386
|
-
verify: Boolean(params.verify)
|
|
536
|
+
verify: Boolean(params.verify),
|
|
387
537
|
};
|
|
388
538
|
}
|
|
389
539
|
|
|
@@ -403,7 +553,7 @@ export function normalizeEvaluateParams(params = {}) {
|
|
|
403
553
|
expression,
|
|
404
554
|
awaitPromise: Boolean(params.awaitPromise),
|
|
405
555
|
timeoutMs: clampInt(params.timeoutMs, 100, 30_000, 5_000),
|
|
406
|
-
returnByValue: params.returnByValue !== false
|
|
556
|
+
returnByValue: params.returnByValue !== false,
|
|
407
557
|
};
|
|
408
558
|
}
|
|
409
559
|
|
|
@@ -416,7 +566,7 @@ export function normalizeConsoleParams(params = {}) {
|
|
|
416
566
|
return {
|
|
417
567
|
level: validLevels.includes(String(params.level ?? '')) ? String(params.level) : 'all',
|
|
418
568
|
clear: Boolean(params.clear),
|
|
419
|
-
limit: clampInt(params.limit, 1, 200, 50)
|
|
569
|
+
limit: clampInt(params.limit, 1, 200, 50),
|
|
420
570
|
};
|
|
421
571
|
}
|
|
422
572
|
|
|
@@ -432,7 +582,7 @@ export function normalizeWaitForParams(params = {}) {
|
|
|
432
582
|
state: validStates.includes(String(params.state ?? ''))
|
|
433
583
|
? /** @type {'attached' | 'detached' | 'visible' | 'hidden'} */ (String(params.state))
|
|
434
584
|
: 'attached',
|
|
435
|
-
timeoutMs: clampInt(params.timeoutMs, 100, 30_000, 5_000)
|
|
585
|
+
timeoutMs: clampInt(params.timeoutMs, 100, 30_000, 5_000),
|
|
436
586
|
};
|
|
437
587
|
}
|
|
438
588
|
|
|
@@ -445,7 +595,7 @@ export function normalizeFindByTextParams(params = {}) {
|
|
|
445
595
|
text: typeof params.text === 'string' ? params.text : '',
|
|
446
596
|
exact: Boolean(params.exact),
|
|
447
597
|
selector: typeof params.selector === 'string' && params.selector.trim() ? params.selector : '*',
|
|
448
|
-
maxResults: clampInt(params.maxResults, 1, 50, 10)
|
|
598
|
+
maxResults: clampInt(params.maxResults, 1, 50, 10),
|
|
449
599
|
};
|
|
450
600
|
}
|
|
451
601
|
|
|
@@ -458,7 +608,7 @@ export function normalizeFindByRoleParams(params = {}) {
|
|
|
458
608
|
role: typeof params.role === 'string' ? params.role : '',
|
|
459
609
|
name: typeof params.name === 'string' ? params.name : '',
|
|
460
610
|
selector: typeof params.selector === 'string' && params.selector.trim() ? params.selector : '*',
|
|
461
|
-
maxResults: clampInt(params.maxResults, 1, 50, 10)
|
|
611
|
+
maxResults: clampInt(params.maxResults, 1, 50, 10),
|
|
462
612
|
};
|
|
463
613
|
}
|
|
464
614
|
|
|
@@ -476,7 +626,7 @@ export function normalizeGetHtmlParams(params = {}) {
|
|
|
476
626
|
elementRef: String(params.elementRef || target.elementRef || ''),
|
|
477
627
|
target,
|
|
478
628
|
outer: Boolean(params.outer),
|
|
479
|
-
maxLength: clampInt(params.maxLength, 32, 50_000, 2000)
|
|
629
|
+
maxLength: clampInt(params.maxLength, 32, 50_000, 2000),
|
|
480
630
|
};
|
|
481
631
|
}
|
|
482
632
|
|
|
@@ -491,7 +641,7 @@ export function normalizeHoverParams(params = {}) {
|
|
|
491
641
|
? /** @type {{ elementRef?: string, selector?: string }} */ (params.target)
|
|
492
642
|
: undefined
|
|
493
643
|
),
|
|
494
|
-
duration: clampInt(params.duration, 0, 5_000, 0)
|
|
644
|
+
duration: clampInt(params.duration, 0, 5_000, 0),
|
|
495
645
|
};
|
|
496
646
|
}
|
|
497
647
|
|
|
@@ -512,7 +662,7 @@ export function normalizeDragParams(params = {}) {
|
|
|
512
662
|
: undefined
|
|
513
663
|
),
|
|
514
664
|
offsetX: Number.isFinite(Number(params.offsetX)) ? Number(params.offsetX) : 0,
|
|
515
|
-
offsetY: Number.isFinite(Number(params.offsetY)) ? Number(params.offsetY) : 0
|
|
665
|
+
offsetY: Number.isFinite(Number(params.offsetY)) ? Number(params.offsetY) : 0,
|
|
516
666
|
};
|
|
517
667
|
}
|
|
518
668
|
|
|
@@ -523,7 +673,7 @@ export function normalizeDragParams(params = {}) {
|
|
|
523
673
|
export function normalizeStorageParams(params = {}) {
|
|
524
674
|
return {
|
|
525
675
|
type: params.type === 'session' ? 'session' : 'local',
|
|
526
|
-
keys: Array.isArray(params.keys) ? params.keys.filter((k) => typeof k === 'string') : null
|
|
676
|
+
keys: Array.isArray(params.keys) ? params.keys.filter((k) => typeof k === 'string') : null,
|
|
527
677
|
};
|
|
528
678
|
}
|
|
529
679
|
|
|
@@ -534,7 +684,7 @@ export function normalizeStorageParams(params = {}) {
|
|
|
534
684
|
export function normalizeWaitForLoadStateParams(params = {}) {
|
|
535
685
|
return {
|
|
536
686
|
waitForLoad: params.waitForLoad !== false,
|
|
537
|
-
timeoutMs: clampInt(params.timeoutMs, 500, 120_000, 15_000)
|
|
687
|
+
timeoutMs: clampInt(params.timeoutMs, 500, 120_000, 15_000),
|
|
538
688
|
};
|
|
539
689
|
}
|
|
540
690
|
|
|
@@ -543,7 +693,8 @@ export function normalizeWaitForLoadStateParams(params = {}) {
|
|
|
543
693
|
* @returns {NormalizedTabCreateParams}
|
|
544
694
|
*/
|
|
545
695
|
export function normalizeTabCreateParams(params = {}) {
|
|
546
|
-
const url =
|
|
696
|
+
const url =
|
|
697
|
+
typeof params.url === 'string' && params.url.trim() ? params.url.trim() : 'about:blank';
|
|
547
698
|
if (url !== 'about:blank') {
|
|
548
699
|
try {
|
|
549
700
|
const parsed = new URL(url);
|
|
@@ -560,7 +711,7 @@ export function normalizeTabCreateParams(params = {}) {
|
|
|
560
711
|
}
|
|
561
712
|
return {
|
|
562
713
|
url,
|
|
563
|
-
active: params.active !== false
|
|
714
|
+
active: params.active !== false,
|
|
564
715
|
};
|
|
565
716
|
}
|
|
566
717
|
|
|
@@ -583,7 +734,7 @@ export function normalizeTabCloseParams(params = {}) {
|
|
|
583
734
|
export function normalizeAccessibilityTreeParams(params = {}) {
|
|
584
735
|
return {
|
|
585
736
|
maxDepth: clampInt(params.maxDepth, 1, 20, DEFAULT_A11Y_MAX_DEPTH),
|
|
586
|
-
maxNodes: clampInt(params.maxNodes, 10, 5000, DEFAULT_A11Y_MAX_NODES)
|
|
737
|
+
maxNodes: clampInt(params.maxNodes, 10, 5000, DEFAULT_A11Y_MAX_NODES),
|
|
587
738
|
};
|
|
588
739
|
}
|
|
589
740
|
|
|
@@ -595,9 +746,10 @@ export function normalizeNetworkParams(params = {}) {
|
|
|
595
746
|
return {
|
|
596
747
|
clear: Boolean(params.clear),
|
|
597
748
|
limit: clampInt(params.limit, 1, 500, DEFAULT_NETWORK_LIMIT),
|
|
598
|
-
urlPattern:
|
|
599
|
-
|
|
600
|
-
|
|
749
|
+
urlPattern:
|
|
750
|
+
typeof params.urlPattern === 'string' && params.urlPattern.trim()
|
|
751
|
+
? params.urlPattern.trim()
|
|
752
|
+
: null,
|
|
601
753
|
};
|
|
602
754
|
}
|
|
603
755
|
|
|
@@ -607,7 +759,7 @@ export function normalizeNetworkParams(params = {}) {
|
|
|
607
759
|
*/
|
|
608
760
|
export function normalizePageTextParams(params = {}) {
|
|
609
761
|
return {
|
|
610
|
-
textBudget: clampInt(params.textBudget, 100, 100_000, DEFAULT_PAGE_TEXT_BUDGET)
|
|
762
|
+
textBudget: clampInt(params.textBudget, 100, 100_000, DEFAULT_PAGE_TEXT_BUDGET),
|
|
611
763
|
};
|
|
612
764
|
}
|
|
613
765
|
|
|
@@ -620,7 +772,7 @@ export function normalizeViewportResizeParams(params = {}) {
|
|
|
620
772
|
width: clampInt(params.width, 320, 7680, DEFAULT_VIEWPORT_WIDTH),
|
|
621
773
|
height: clampInt(params.height, 200, 4320, DEFAULT_VIEWPORT_HEIGHT),
|
|
622
774
|
deviceScaleFactor: clampInt(params.deviceScaleFactor, 0, 4, 0),
|
|
623
|
-
reset: Boolean(params.reset)
|
|
775
|
+
reset: Boolean(params.reset),
|
|
624
776
|
};
|
|
625
777
|
}
|
|
626
778
|
|
|
@@ -641,24 +793,37 @@ export function createRuntimeContext() {
|
|
|
641
793
|
return {
|
|
642
794
|
v: PROTOCOL_VERSION,
|
|
643
795
|
budgets: {
|
|
644
|
-
quick: {
|
|
645
|
-
|
|
646
|
-
|
|
796
|
+
quick: {
|
|
797
|
+
n: BUDGET_PRESETS.quick.maxNodes,
|
|
798
|
+
d: BUDGET_PRESETS.quick.maxDepth,
|
|
799
|
+
t: BUDGET_PRESETS.quick.textBudget,
|
|
800
|
+
},
|
|
801
|
+
normal: {
|
|
802
|
+
n: BUDGET_PRESETS.normal.maxNodes,
|
|
803
|
+
d: BUDGET_PRESETS.normal.maxDepth,
|
|
804
|
+
t: BUDGET_PRESETS.normal.textBudget,
|
|
805
|
+
},
|
|
806
|
+
deep: {
|
|
807
|
+
n: BUDGET_PRESETS.deep.maxNodes,
|
|
808
|
+
d: BUDGET_PRESETS.deep.maxDepth,
|
|
809
|
+
t: BUDGET_PRESETS.deep.textBudget,
|
|
810
|
+
},
|
|
647
811
|
},
|
|
648
812
|
methods: methodGroups,
|
|
649
813
|
errors: {
|
|
650
|
-
ACCESS_DENIED:
|
|
814
|
+
ACCESS_DENIED:
|
|
815
|
+
'Browser Bridge is off for this window or the page is restricted; if access is off, the first denied call surfaces an Enable cue in the extension UI',
|
|
651
816
|
TAB_MISMATCH: 'Tab closed or not found',
|
|
652
817
|
ELEMENT_STALE: 'Element removed from DOM - re-query',
|
|
653
818
|
INVALID_REQUEST: 'Malformed method or params',
|
|
654
819
|
TIMEOUT: 'Operation exceeded time limit',
|
|
655
820
|
RATE_LIMITED: 'Too many requests - back off',
|
|
656
821
|
INTERNAL_ERROR: 'Unexpected extension error',
|
|
657
|
-
EXTENSION_DISCONNECTED: 'Extension not connected to daemon - check Chrome'
|
|
822
|
+
EXTENSION_DISCONNECTED: 'Extension not connected to daemon - check Chrome',
|
|
658
823
|
},
|
|
659
824
|
tips: [
|
|
660
825
|
'dom.query quick budget first; widen only if truncated',
|
|
661
|
-
|
|
826
|
+
"Reuse elementRef; don't re-query",
|
|
662
827
|
'Set attributeAllowlist for focused DOM reads',
|
|
663
828
|
'patch.apply_styles before patch.apply_dom',
|
|
664
829
|
'Verify with get_box_model not screenshots',
|
|
@@ -676,7 +841,7 @@ export function createRuntimeContext() {
|
|
|
676
841
|
'performance.get_metrics for Core Web Vitals and load timing',
|
|
677
842
|
'viewport.resize to test responsive layouts',
|
|
678
843
|
'Prefer screenshot.capture_element, or a tight screenshot.capture_region when element capture cannot express the needed area',
|
|
679
|
-
'page.get_storage reads localStorage/sessionStorage without evaluate'
|
|
844
|
+
'page.get_storage reads localStorage/sessionStorage without evaluate',
|
|
680
845
|
],
|
|
681
846
|
flow: [
|
|
682
847
|
'health.ping',
|
|
@@ -686,7 +851,7 @@ export function createRuntimeContext() {
|
|
|
686
851
|
'patch.apply_styles',
|
|
687
852
|
'layout.get_box_model',
|
|
688
853
|
'page.get_console',
|
|
689
|
-
'patch.rollback'
|
|
854
|
+
'patch.rollback',
|
|
690
855
|
],
|
|
691
856
|
limits: {
|
|
692
857
|
maxNodes: { min: 1, max: 250, default: DEFAULT_MAX_NODES },
|
|
@@ -699,7 +864,11 @@ export function createRuntimeContext() {
|
|
|
699
864
|
a11yMaxNodes: { min: 10, max: 5000, default: DEFAULT_A11Y_MAX_NODES },
|
|
700
865
|
networkLimit: { min: 1, max: 500, default: DEFAULT_NETWORK_LIMIT },
|
|
701
866
|
consoleLimit: { min: 1, max: 200, default: DEFAULT_CONSOLE_LIMIT },
|
|
702
|
-
pageTextBudget: {
|
|
703
|
-
|
|
867
|
+
pageTextBudget: {
|
|
868
|
+
min: 100,
|
|
869
|
+
max: 100000,
|
|
870
|
+
default: DEFAULT_PAGE_TEXT_BUDGET,
|
|
871
|
+
},
|
|
872
|
+
},
|
|
704
873
|
};
|
|
705
874
|
}
|