@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
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
import os from 'node:os';
|
|
3
4
|
import {
|
|
4
5
|
bridgeMethodNeedsTab,
|
|
6
|
+
createRuntimeContext,
|
|
5
7
|
DEFAULT_CONSOLE_LIMIT,
|
|
6
8
|
DEFAULT_MAX_HTML_LENGTH,
|
|
7
9
|
DEFAULT_NETWORK_LIMIT,
|
|
@@ -9,7 +11,7 @@ import {
|
|
|
9
11
|
getBudgetPreset,
|
|
10
12
|
getErrorRecovery,
|
|
11
13
|
isBudgetPresetName,
|
|
12
|
-
|
|
14
|
+
METHOD_SET,
|
|
13
15
|
summarizeBatchErrorItem,
|
|
14
16
|
summarizeBatchResponseItem,
|
|
15
17
|
} from '../../protocol/src/index.js';
|
|
@@ -17,17 +19,16 @@ import {
|
|
|
17
19
|
getDoctorReport,
|
|
18
20
|
requestBridge,
|
|
19
21
|
resolveRef,
|
|
20
|
-
withBridgeClient
|
|
22
|
+
withBridgeClient,
|
|
21
23
|
} from '../../agent-client/src/runtime.js';
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
summarizeBridgeResponse,
|
|
25
|
-
} from '../../agent-client/src/subagent.js';
|
|
24
|
+
import { annotateBridgeSummary, summarizeBridgeResponse } from '../../agent-client/src/subagent.js';
|
|
25
|
+
import { collectSetupStatus } from '../../agent-client/src/setup-status.js';
|
|
26
26
|
|
|
27
27
|
/** @typedef {import('../../protocol/src/types.js').BridgeMethod} BridgeMethod */
|
|
28
28
|
/** @typedef {import('../../protocol/src/types.js').BridgeResponse} BridgeResponse */
|
|
29
29
|
|
|
30
30
|
const REQUEST_SOURCE = 'mcp';
|
|
31
|
+
const HOME_DIR = os.homedir();
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* @typedef {{
|
|
@@ -47,7 +48,7 @@ function createToolResult(summary, structuredContent = {}, isError = false) {
|
|
|
47
48
|
const toolResult = {
|
|
48
49
|
content: [{ type: /** @type {'text'} */ ('text'), text: summary }],
|
|
49
50
|
structuredContent,
|
|
50
|
-
...(isError ? { isError: true } : {})
|
|
51
|
+
...(isError ? { isError: true } : {}),
|
|
51
52
|
};
|
|
52
53
|
const delivered = estimateJsonPayloadCost(toolResult);
|
|
53
54
|
return {
|
|
@@ -77,10 +78,14 @@ function summarizeToolResponse(response, method) {
|
|
|
77
78
|
*/
|
|
78
79
|
function summarizeToolError(error) {
|
|
79
80
|
const message = error instanceof Error ? error.message : String(error);
|
|
80
|
-
return createToolResult(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
return createToolResult(
|
|
82
|
+
`ERROR: ${message}`,
|
|
83
|
+
{
|
|
84
|
+
ok: false,
|
|
85
|
+
evidence: null,
|
|
86
|
+
},
|
|
87
|
+
true
|
|
88
|
+
);
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
/**
|
|
@@ -235,12 +240,12 @@ function applyHtmlBudgetPreset(args) {
|
|
|
235
240
|
*/
|
|
236
241
|
async function requestBridgeWithRetry(client, method, params, options) {
|
|
237
242
|
const response = await requestBridge(client, method, params, options);
|
|
238
|
-
const recovery = !response.ok && response.error
|
|
239
|
-
? getErrorRecovery(response.error.code)
|
|
240
|
-
: null;
|
|
243
|
+
const recovery = !response.ok && response.error ? getErrorRecovery(response.error.code) : null;
|
|
241
244
|
if (!response.ok && recovery?.retry) {
|
|
242
245
|
const delay = recovery.retryAfterMs ?? 1000;
|
|
243
|
-
process.stderr.write(
|
|
246
|
+
process.stderr.write(
|
|
247
|
+
`[bbx-mcp] Retrying ${method} after ${delay}ms (${response.error.code})\n`
|
|
248
|
+
);
|
|
244
249
|
await new Promise((r) => setTimeout(r, delay));
|
|
245
250
|
return requestBridge(client, method, params, options);
|
|
246
251
|
}
|
|
@@ -285,10 +290,10 @@ async function dispatchToolAction(actions, args, toolName) {
|
|
|
285
290
|
const requestedTabId = typeof args.tabId === 'number' ? args.tabId : null;
|
|
286
291
|
const ref = entry.ref
|
|
287
292
|
? await resolveToolRef(
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
293
|
+
client,
|
|
294
|
+
/** @type {{ elementRef?: string, selector?: string }} */ (args),
|
|
295
|
+
requestedTabId
|
|
296
|
+
)
|
|
292
297
|
: undefined;
|
|
293
298
|
const response = await requestBridgeWithRetry(client, entry.method, entry.params(args, ref), {
|
|
294
299
|
tabId: requestedTabId,
|
|
@@ -305,12 +310,13 @@ async function dispatchToolAction(actions, args, toolName) {
|
|
|
305
310
|
export async function handleStatusTool() {
|
|
306
311
|
try {
|
|
307
312
|
const report = await getDoctorReport();
|
|
308
|
-
const summary =
|
|
309
|
-
|
|
310
|
-
|
|
313
|
+
const summary =
|
|
314
|
+
report.issues.length === 0
|
|
315
|
+
? 'Browser Bridge is ready.'
|
|
316
|
+
: `Browser Bridge has ${report.issues.length} readiness issue(s).`;
|
|
311
317
|
return createToolResult(summary, {
|
|
312
318
|
ok: report.issues.length === 0,
|
|
313
|
-
evidence: report
|
|
319
|
+
evidence: report,
|
|
314
320
|
});
|
|
315
321
|
} catch (error) {
|
|
316
322
|
return summarizeToolError(error);
|
|
@@ -328,7 +334,7 @@ export async function handleTabsTool(args) {
|
|
|
328
334
|
if (args.action === 'create') {
|
|
329
335
|
return callBridgeTool('tabs.create', {
|
|
330
336
|
url: args.url,
|
|
331
|
-
active: args.active
|
|
337
|
+
active: args.active,
|
|
332
338
|
});
|
|
333
339
|
}
|
|
334
340
|
if (args.action === 'close') {
|
|
@@ -343,15 +349,78 @@ export async function handleTabsTool(args) {
|
|
|
343
349
|
/**
|
|
344
350
|
/** @type {Record<string, ToolAction>} */
|
|
345
351
|
export const DOM_ACTIONS = {
|
|
346
|
-
query:
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
352
|
+
query: {
|
|
353
|
+
ref: false,
|
|
354
|
+
method: 'dom.query',
|
|
355
|
+
params: (a) => ({
|
|
356
|
+
selector: a.selector || 'body',
|
|
357
|
+
withinRef: a.withinRef,
|
|
358
|
+
maxNodes: a.maxNodes,
|
|
359
|
+
maxDepth: a.maxDepth,
|
|
360
|
+
textBudget: a.textBudget,
|
|
361
|
+
includeBbox: a.includeBbox,
|
|
362
|
+
attributeAllowlist: a.attributeAllowlist,
|
|
363
|
+
}),
|
|
364
|
+
},
|
|
365
|
+
describe: {
|
|
366
|
+
ref: true,
|
|
367
|
+
method: 'dom.describe',
|
|
368
|
+
params: (_, r) => ({ elementRef: r }),
|
|
369
|
+
},
|
|
370
|
+
text: {
|
|
371
|
+
ref: true,
|
|
372
|
+
method: 'dom.get_text',
|
|
373
|
+
params: (a, r) => ({ elementRef: r, textBudget: a.textBudget }),
|
|
374
|
+
},
|
|
375
|
+
attributes: {
|
|
376
|
+
ref: true,
|
|
377
|
+
method: 'dom.get_attributes',
|
|
378
|
+
params: (a, r) => ({ elementRef: r, attributes: a.attributes || [] }),
|
|
379
|
+
},
|
|
380
|
+
wait: {
|
|
381
|
+
ref: false,
|
|
382
|
+
method: 'dom.wait_for',
|
|
383
|
+
params: (a) => ({
|
|
384
|
+
selector: a.selector,
|
|
385
|
+
text: a.text,
|
|
386
|
+
state: a.state,
|
|
387
|
+
timeoutMs: a.timeoutMs,
|
|
388
|
+
}),
|
|
389
|
+
},
|
|
390
|
+
find_text: {
|
|
391
|
+
ref: false,
|
|
392
|
+
method: 'dom.find_by_text',
|
|
393
|
+
params: (a) => ({
|
|
394
|
+
text: a.text,
|
|
395
|
+
exact: a.exact,
|
|
396
|
+
selector: a.selector,
|
|
397
|
+
maxResults: a.maxResults,
|
|
398
|
+
}),
|
|
399
|
+
},
|
|
400
|
+
find_role: {
|
|
401
|
+
ref: false,
|
|
402
|
+
method: 'dom.find_by_role',
|
|
403
|
+
params: (a) => ({
|
|
404
|
+
role: a.role,
|
|
405
|
+
name: a.name,
|
|
406
|
+
selector: a.selector,
|
|
407
|
+
maxResults: a.maxResults,
|
|
408
|
+
}),
|
|
409
|
+
},
|
|
410
|
+
html: {
|
|
411
|
+
ref: true,
|
|
412
|
+
method: 'dom.get_html',
|
|
413
|
+
params: (a, r) => ({
|
|
414
|
+
elementRef: r,
|
|
415
|
+
outer: a.outer,
|
|
416
|
+
maxLength: a.maxLength,
|
|
417
|
+
}),
|
|
418
|
+
},
|
|
419
|
+
accessibility_tree: {
|
|
420
|
+
ref: false,
|
|
421
|
+
method: 'dom.get_accessibility_tree',
|
|
422
|
+
params: (a) => ({ maxNodes: a.maxNodes, maxDepth: a.maxDepth }),
|
|
423
|
+
},
|
|
355
424
|
};
|
|
356
425
|
|
|
357
426
|
/**
|
|
@@ -375,10 +444,26 @@ export async function handleDomTool(args) {
|
|
|
375
444
|
|
|
376
445
|
/** @type {Record<string, ToolAction>} */
|
|
377
446
|
export const STYLES_LAYOUT_ACTIONS = {
|
|
378
|
-
computed:
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
447
|
+
computed: {
|
|
448
|
+
ref: true,
|
|
449
|
+
method: 'styles.get_computed',
|
|
450
|
+
params: (a, r) => ({ elementRef: r, properties: a.properties }),
|
|
451
|
+
},
|
|
452
|
+
matched_rules: {
|
|
453
|
+
ref: true,
|
|
454
|
+
method: 'styles.get_matched_rules',
|
|
455
|
+
params: (_, r) => ({ elementRef: r }),
|
|
456
|
+
},
|
|
457
|
+
box_model: {
|
|
458
|
+
ref: true,
|
|
459
|
+
method: 'layout.get_box_model',
|
|
460
|
+
params: (_, r) => ({ elementRef: r }),
|
|
461
|
+
},
|
|
462
|
+
hit_test: {
|
|
463
|
+
ref: false,
|
|
464
|
+
method: 'layout.hit_test',
|
|
465
|
+
params: (a) => ({ x: a.x, y: a.y }),
|
|
466
|
+
},
|
|
382
467
|
};
|
|
383
468
|
|
|
384
469
|
/**
|
|
@@ -391,14 +476,41 @@ export async function handleStylesLayoutTool(args) {
|
|
|
391
476
|
|
|
392
477
|
/** @type {Record<string, { method: BridgeMethod, params: (a: Record<string, unknown>) => Record<string, unknown> }>} */
|
|
393
478
|
export const PAGE_ACTIONS = {
|
|
394
|
-
state:
|
|
395
|
-
evaluate:
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
479
|
+
state: { method: 'page.get_state', params: () => ({}) },
|
|
480
|
+
evaluate: {
|
|
481
|
+
method: 'page.evaluate',
|
|
482
|
+
params: (a) => ({
|
|
483
|
+
expression: a.expression,
|
|
484
|
+
awaitPromise: a.awaitPromise,
|
|
485
|
+
timeoutMs: a.timeoutMs,
|
|
486
|
+
returnByValue: a.returnByValue,
|
|
487
|
+
}),
|
|
488
|
+
},
|
|
489
|
+
console: {
|
|
490
|
+
method: 'page.get_console',
|
|
491
|
+
params: (a) => ({ level: a.level, clear: a.clear, limit: a.limit }),
|
|
492
|
+
},
|
|
493
|
+
wait_for_load: {
|
|
494
|
+
method: 'page.wait_for_load_state',
|
|
495
|
+
params: (a) => ({ timeoutMs: a.timeoutMs }),
|
|
496
|
+
},
|
|
497
|
+
storage: {
|
|
498
|
+
method: 'page.get_storage',
|
|
499
|
+
params: (a) => ({ type: a.type, keys: a.keys }),
|
|
500
|
+
},
|
|
501
|
+
text: {
|
|
502
|
+
method: 'page.get_text',
|
|
503
|
+
params: (a) => ({ textBudget: a.textBudget }),
|
|
504
|
+
},
|
|
505
|
+
network: {
|
|
506
|
+
method: 'page.get_network',
|
|
507
|
+
params: (a) => ({
|
|
508
|
+
clear: a.clear,
|
|
509
|
+
limit: a.limit,
|
|
510
|
+
urlPattern: a.urlPattern,
|
|
511
|
+
}),
|
|
512
|
+
},
|
|
513
|
+
performance: { method: 'performance.get_metrics', params: () => ({}) },
|
|
402
514
|
};
|
|
403
515
|
|
|
404
516
|
/**
|
|
@@ -432,12 +544,39 @@ export async function handlePageTool(args) {
|
|
|
432
544
|
|
|
433
545
|
/** @type {Record<string, { method: BridgeMethod, params: (a: Record<string, unknown>) => Record<string, unknown> }>} */
|
|
434
546
|
export const NAVIGATION_ACTIONS = {
|
|
435
|
-
navigate:
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
547
|
+
navigate: {
|
|
548
|
+
method: 'navigation.navigate',
|
|
549
|
+
params: (a) => ({
|
|
550
|
+
url: a.url,
|
|
551
|
+
waitForLoad: a.waitForLoad,
|
|
552
|
+
timeoutMs: a.timeoutMs,
|
|
553
|
+
}),
|
|
554
|
+
},
|
|
555
|
+
reload: {
|
|
556
|
+
method: 'navigation.reload',
|
|
557
|
+
params: (a) => ({ waitForLoad: a.waitForLoad, timeoutMs: a.timeoutMs }),
|
|
558
|
+
},
|
|
559
|
+
go_back: {
|
|
560
|
+
method: 'navigation.go_back',
|
|
561
|
+
params: (a) => ({ waitForLoad: a.waitForLoad, timeoutMs: a.timeoutMs }),
|
|
562
|
+
},
|
|
563
|
+
go_forward: {
|
|
564
|
+
method: 'navigation.go_forward',
|
|
565
|
+
params: (a) => ({ waitForLoad: a.waitForLoad, timeoutMs: a.timeoutMs }),
|
|
566
|
+
},
|
|
567
|
+
scroll: {
|
|
568
|
+
method: 'viewport.scroll',
|
|
569
|
+
params: (a) => ({
|
|
570
|
+
top: a.top,
|
|
571
|
+
left: a.left,
|
|
572
|
+
behavior: a.behavior,
|
|
573
|
+
relative: a.relative,
|
|
574
|
+
}),
|
|
575
|
+
},
|
|
576
|
+
resize: {
|
|
577
|
+
method: 'viewport.resize',
|
|
578
|
+
params: (a) => ({ width: a.width, height: a.height, reset: a.reset }),
|
|
579
|
+
},
|
|
441
580
|
};
|
|
442
581
|
|
|
443
582
|
/**
|
|
@@ -459,15 +598,16 @@ export const INPUT_ACTION_METHODS = {
|
|
|
459
598
|
focus: 'input.focus',
|
|
460
599
|
type: 'input.type',
|
|
461
600
|
press_key: 'input.press_key',
|
|
601
|
+
cdp_press_key: 'cdp.dispatch_key_event',
|
|
462
602
|
set_checked: 'input.set_checked',
|
|
463
603
|
select_option: 'input.select_option',
|
|
464
604
|
hover: 'input.hover',
|
|
465
605
|
drag: 'input.drag',
|
|
466
|
-
scroll_into_view: 'input.scroll_into_view'
|
|
606
|
+
scroll_into_view: 'input.scroll_into_view',
|
|
467
607
|
};
|
|
468
608
|
|
|
469
609
|
/**
|
|
470
|
-
* @param {{ action: string, elementRef?: string, selector?: string, button?: string, clickCount?: number, text?: string, clear?: boolean, submit?: boolean, key?: string, modifiers?: string[], checked?: boolean, values?: string[], labels?: string[], indexes?: number[], duration?: number, sourceElementRef?: string, sourceSelector?: string, destinationElementRef?: string, destinationSelector?: string, offsetX?: number, offsetY?: number, tabId?: number, budgetPreset?: 'quick' | 'normal' | 'deep' }} args
|
|
610
|
+
* @param {{ action: string, elementRef?: string, selector?: string, button?: string, clickCount?: number, text?: string, clear?: boolean, submit?: boolean, key?: string, code?: string, modifiers?: string[], checked?: boolean, values?: string[], labels?: string[], indexes?: number[], duration?: number, sourceElementRef?: string, sourceSelector?: string, destinationElementRef?: string, destinationSelector?: string, offsetX?: number, offsetY?: number, tabId?: number, budgetPreset?: 'quick' | 'normal' | 'deep' }} args
|
|
471
611
|
* @returns {Promise<ToolResult>}
|
|
472
612
|
*/
|
|
473
613
|
export async function handleInputTool(args) {
|
|
@@ -479,118 +619,190 @@ export async function handleInputTool(args) {
|
|
|
479
619
|
|
|
480
620
|
switch (args.action) {
|
|
481
621
|
case 'click': {
|
|
482
|
-
const response = await requestBridge(
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
622
|
+
const response = await requestBridge(
|
|
623
|
+
client,
|
|
624
|
+
'input.click',
|
|
625
|
+
{
|
|
626
|
+
target: await elementTarget(),
|
|
627
|
+
button: args.button,
|
|
628
|
+
clickCount: args.clickCount,
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
tabId: requestedTabId,
|
|
632
|
+
source: REQUEST_SOURCE,
|
|
633
|
+
tokenBudget: getToolTokenBudget(args),
|
|
634
|
+
}
|
|
635
|
+
);
|
|
491
636
|
return summarizeToolResponse(response, 'input.click');
|
|
492
637
|
}
|
|
493
638
|
case 'focus': {
|
|
494
|
-
const response = await requestBridge(
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
639
|
+
const response = await requestBridge(
|
|
640
|
+
client,
|
|
641
|
+
'input.focus',
|
|
642
|
+
{
|
|
643
|
+
target: await elementTarget(),
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
tabId: requestedTabId,
|
|
647
|
+
source: REQUEST_SOURCE,
|
|
648
|
+
tokenBudget: getToolTokenBudget(args),
|
|
649
|
+
}
|
|
650
|
+
);
|
|
501
651
|
return summarizeToolResponse(response, 'input.focus');
|
|
502
652
|
}
|
|
503
653
|
case 'type': {
|
|
504
|
-
const response = await requestBridge(
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
654
|
+
const response = await requestBridge(
|
|
655
|
+
client,
|
|
656
|
+
'input.type',
|
|
657
|
+
{
|
|
658
|
+
target: await elementTarget(),
|
|
659
|
+
text: args.text,
|
|
660
|
+
clear: args.clear,
|
|
661
|
+
submit: args.submit,
|
|
662
|
+
},
|
|
663
|
+
{
|
|
664
|
+
tabId: requestedTabId,
|
|
665
|
+
source: REQUEST_SOURCE,
|
|
666
|
+
tokenBudget: getToolTokenBudget(args),
|
|
667
|
+
}
|
|
668
|
+
);
|
|
514
669
|
return summarizeToolResponse(response, 'input.type');
|
|
515
670
|
}
|
|
516
671
|
case 'press_key': {
|
|
517
|
-
const target =
|
|
518
|
-
const response = await requestBridge(
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
672
|
+
const target = args.elementRef || args.selector ? await elementTarget() : undefined;
|
|
673
|
+
const response = await requestBridge(
|
|
674
|
+
client,
|
|
675
|
+
'input.press_key',
|
|
676
|
+
{
|
|
677
|
+
target,
|
|
678
|
+
key: args.key,
|
|
679
|
+
modifiers: args.modifiers,
|
|
680
|
+
},
|
|
681
|
+
{
|
|
682
|
+
tabId: requestedTabId,
|
|
683
|
+
source: REQUEST_SOURCE,
|
|
684
|
+
tokenBudget: getToolTokenBudget(args),
|
|
685
|
+
}
|
|
686
|
+
);
|
|
527
687
|
return summarizeToolResponse(response, 'input.press_key');
|
|
528
688
|
}
|
|
689
|
+
case 'cdp_press_key': {
|
|
690
|
+
const response = await requestBridge(
|
|
691
|
+
client,
|
|
692
|
+
'cdp.dispatch_key_event',
|
|
693
|
+
{
|
|
694
|
+
key: args.key,
|
|
695
|
+
code: args.code,
|
|
696
|
+
modifiers: args.modifiers,
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
tabId: requestedTabId,
|
|
700
|
+
source: REQUEST_SOURCE,
|
|
701
|
+
tokenBudget: getToolTokenBudget(args),
|
|
702
|
+
}
|
|
703
|
+
);
|
|
704
|
+
return summarizeToolResponse(response, 'cdp.dispatch_key_event');
|
|
705
|
+
}
|
|
529
706
|
case 'set_checked': {
|
|
530
|
-
const response = await requestBridge(
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
707
|
+
const response = await requestBridge(
|
|
708
|
+
client,
|
|
709
|
+
'input.set_checked',
|
|
710
|
+
{
|
|
711
|
+
target: await elementTarget(),
|
|
712
|
+
checked: args.checked,
|
|
713
|
+
},
|
|
714
|
+
{
|
|
715
|
+
tabId: requestedTabId,
|
|
716
|
+
source: REQUEST_SOURCE,
|
|
717
|
+
tokenBudget: getToolTokenBudget(args),
|
|
718
|
+
}
|
|
719
|
+
);
|
|
538
720
|
return summarizeToolResponse(response, 'input.set_checked');
|
|
539
721
|
}
|
|
540
722
|
case 'select_option': {
|
|
541
|
-
const response = await requestBridge(
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
723
|
+
const response = await requestBridge(
|
|
724
|
+
client,
|
|
725
|
+
'input.select_option',
|
|
726
|
+
{
|
|
727
|
+
target: await elementTarget(),
|
|
728
|
+
values: args.values,
|
|
729
|
+
labels: args.labels,
|
|
730
|
+
indexes: args.indexes,
|
|
731
|
+
},
|
|
732
|
+
{
|
|
733
|
+
tabId: requestedTabId,
|
|
734
|
+
source: REQUEST_SOURCE,
|
|
735
|
+
tokenBudget: getToolTokenBudget(args),
|
|
736
|
+
}
|
|
737
|
+
);
|
|
551
738
|
return summarizeToolResponse(response, 'input.select_option');
|
|
552
739
|
}
|
|
553
740
|
case 'hover': {
|
|
554
|
-
const response = await requestBridge(
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
741
|
+
const response = await requestBridge(
|
|
742
|
+
client,
|
|
743
|
+
'input.hover',
|
|
744
|
+
{
|
|
745
|
+
target: await elementTarget(),
|
|
746
|
+
duration: args.duration,
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
tabId: requestedTabId,
|
|
750
|
+
source: REQUEST_SOURCE,
|
|
751
|
+
tokenBudget: getToolTokenBudget(args),
|
|
752
|
+
}
|
|
753
|
+
);
|
|
562
754
|
return summarizeToolResponse(response, 'input.hover');
|
|
563
755
|
}
|
|
564
756
|
case 'drag': {
|
|
565
757
|
const source = {
|
|
566
|
-
elementRef:
|
|
758
|
+
elementRef:
|
|
759
|
+
args.sourceElementRef ||
|
|
760
|
+
(args.sourceSelector
|
|
761
|
+
? await resolveRef(client, args.sourceSelector, requestedTabId, REQUEST_SOURCE)
|
|
762
|
+
: ''),
|
|
567
763
|
};
|
|
568
764
|
const destination = {
|
|
569
|
-
elementRef:
|
|
765
|
+
elementRef:
|
|
766
|
+
args.destinationElementRef ||
|
|
767
|
+
(args.destinationSelector
|
|
768
|
+
? await resolveRef(client, args.destinationSelector, requestedTabId, REQUEST_SOURCE)
|
|
769
|
+
: ''),
|
|
570
770
|
};
|
|
571
771
|
if (!source.elementRef || !destination.elementRef) {
|
|
572
|
-
return summarizeToolError(
|
|
772
|
+
return summarizeToolError(
|
|
773
|
+
'sourceElementRef/sourceSelector and destinationElementRef/destinationSelector are required for drag.'
|
|
774
|
+
);
|
|
573
775
|
}
|
|
574
|
-
const response = await requestBridge(
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
776
|
+
const response = await requestBridge(
|
|
777
|
+
client,
|
|
778
|
+
'input.drag',
|
|
779
|
+
{
|
|
780
|
+
source,
|
|
781
|
+
destination,
|
|
782
|
+
offsetX: args.offsetX,
|
|
783
|
+
offsetY: args.offsetY,
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
tabId: requestedTabId,
|
|
787
|
+
source: REQUEST_SOURCE,
|
|
788
|
+
tokenBudget: getToolTokenBudget(args),
|
|
789
|
+
}
|
|
790
|
+
);
|
|
584
791
|
return summarizeToolResponse(response, 'input.drag');
|
|
585
792
|
}
|
|
586
793
|
case 'scroll_into_view': {
|
|
587
|
-
const response = await requestBridge(
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
794
|
+
const response = await requestBridge(
|
|
795
|
+
client,
|
|
796
|
+
'input.scroll_into_view',
|
|
797
|
+
{
|
|
798
|
+
target: await elementTarget(),
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
tabId: requestedTabId,
|
|
802
|
+
source: REQUEST_SOURCE,
|
|
803
|
+
tokenBudget: getToolTokenBudget(args),
|
|
804
|
+
}
|
|
805
|
+
);
|
|
594
806
|
return summarizeToolResponse(response, 'input.scroll_into_view');
|
|
595
807
|
}
|
|
596
808
|
default:
|
|
@@ -601,23 +813,50 @@ export async function handleInputTool(args) {
|
|
|
601
813
|
|
|
602
814
|
/** @type {Record<string, ToolAction>} */
|
|
603
815
|
export const PATCH_ACTIONS = {
|
|
604
|
-
apply_styles:
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
816
|
+
apply_styles: {
|
|
817
|
+
ref: true,
|
|
818
|
+
method: 'patch.apply_styles',
|
|
819
|
+
params: (a, r) => ({
|
|
820
|
+
target: { elementRef: r },
|
|
821
|
+
declarations: a.declarations,
|
|
822
|
+
important: a.important,
|
|
823
|
+
verify: a.verify,
|
|
824
|
+
}),
|
|
825
|
+
},
|
|
826
|
+
apply_dom: {
|
|
827
|
+
ref: true,
|
|
828
|
+
method: 'patch.apply_dom',
|
|
829
|
+
params: (a, r) => {
|
|
830
|
+
const operation = typeof a.operation === 'string' ? a.operation : '';
|
|
831
|
+
/** @type {Record<string, string>} */
|
|
832
|
+
const opMap = {
|
|
833
|
+
setAttribute: 'set_attribute',
|
|
834
|
+
removeAttribute: 'remove_attribute',
|
|
835
|
+
addClass: 'toggle_class',
|
|
836
|
+
removeClass: 'toggle_class',
|
|
837
|
+
setTextContent: 'set_text',
|
|
838
|
+
setProperty: 'set_attribute',
|
|
839
|
+
};
|
|
840
|
+
return {
|
|
841
|
+
target: { elementRef: r },
|
|
842
|
+
operation: opMap[operation] || operation,
|
|
843
|
+
value: a.value,
|
|
844
|
+
name: a.name,
|
|
845
|
+
verify: a.verify,
|
|
846
|
+
};
|
|
847
|
+
},
|
|
848
|
+
},
|
|
849
|
+
list: { ref: false, method: 'patch.list', params: () => ({}) },
|
|
850
|
+
rollback: {
|
|
851
|
+
ref: false,
|
|
852
|
+
method: 'patch.rollback',
|
|
853
|
+
params: (a) => ({ patchId: a.patchId }),
|
|
854
|
+
},
|
|
855
|
+
commit_baseline: {
|
|
856
|
+
ref: false,
|
|
857
|
+
method: 'patch.commit_session_baseline',
|
|
858
|
+
params: () => ({}),
|
|
859
|
+
},
|
|
621
860
|
};
|
|
622
861
|
|
|
623
862
|
/**
|
|
@@ -630,13 +869,37 @@ export async function handlePatchTool(args) {
|
|
|
630
869
|
|
|
631
870
|
/** @type {Record<string, ToolAction>} */
|
|
632
871
|
export const CAPTURE_ACTIONS = {
|
|
633
|
-
element:
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
872
|
+
element: {
|
|
873
|
+
ref: true,
|
|
874
|
+
method: 'screenshot.capture_element',
|
|
875
|
+
params: (_, r) => ({ elementRef: r }),
|
|
876
|
+
},
|
|
877
|
+
region: {
|
|
878
|
+
ref: false,
|
|
879
|
+
method: 'screenshot.capture_region',
|
|
880
|
+
params: (a) => /** @type {Record<string, unknown>} */ (a.rect || {}),
|
|
881
|
+
},
|
|
882
|
+
full_page: {
|
|
883
|
+
ref: false,
|
|
884
|
+
method: 'screenshot.capture_full_page',
|
|
885
|
+
params: () => ({}),
|
|
886
|
+
},
|
|
887
|
+
cdp_document: { ref: false, method: 'cdp.get_document', params: () => ({}) },
|
|
888
|
+
cdp_dom_snapshot: {
|
|
889
|
+
ref: false,
|
|
890
|
+
method: 'cdp.get_dom_snapshot',
|
|
891
|
+
params: () => ({}),
|
|
892
|
+
},
|
|
893
|
+
cdp_box_model: {
|
|
894
|
+
ref: true,
|
|
895
|
+
method: 'cdp.get_box_model',
|
|
896
|
+
params: (_, r) => ({ elementRef: r }),
|
|
897
|
+
},
|
|
898
|
+
cdp_computed_styles: {
|
|
899
|
+
ref: true,
|
|
900
|
+
method: 'cdp.get_computed_styles_for_node',
|
|
901
|
+
params: (_, r) => ({ elementRef: r }),
|
|
902
|
+
},
|
|
640
903
|
};
|
|
641
904
|
|
|
642
905
|
/**
|
|
@@ -655,9 +918,11 @@ export async function handleCaptureTool(args) {
|
|
|
655
918
|
*/
|
|
656
919
|
export async function handleSkillTool() {
|
|
657
920
|
try {
|
|
658
|
-
const { createRuntimeContext } = await import('../../protocol/src/index.js');
|
|
659
921
|
const ctx = createRuntimeContext();
|
|
660
|
-
return createToolResult('Runtime context retrieved.', {
|
|
922
|
+
return createToolResult('Runtime context retrieved.', {
|
|
923
|
+
ok: true,
|
|
924
|
+
runtimeContext: ctx,
|
|
925
|
+
});
|
|
661
926
|
} catch (error) {
|
|
662
927
|
return summarizeToolError(error);
|
|
663
928
|
}
|
|
@@ -670,18 +935,15 @@ export async function handleSkillTool() {
|
|
|
670
935
|
* @returns {Promise<ToolResult>}
|
|
671
936
|
*/
|
|
672
937
|
export async function handleSetupTool(args) {
|
|
673
|
-
const
|
|
674
|
-
const projectPath = args.global !== false ? (await import('node:os')).homedir() : process.cwd();
|
|
938
|
+
const projectPath = args.global !== false ? HOME_DIR : process.cwd();
|
|
675
939
|
const status = await collectSetupStatus({
|
|
676
940
|
global: args.global !== false,
|
|
677
941
|
cwd: process.cwd(),
|
|
678
|
-
projectPath
|
|
942
|
+
projectPath,
|
|
679
943
|
});
|
|
680
944
|
const configuredMcp = status.mcpClients.filter((e) => e.configured).length;
|
|
681
945
|
const installedSkills = status.skillTargets.filter((e) => e.installed).length;
|
|
682
|
-
const summary = configuredMcp
|
|
683
|
-
? 'No MCP or skill setup found. Run `bbx install-mcp` and `bbx install-skill`.'
|
|
684
|
-
: `Setup: ${configuredMcp}/${status.mcpClients.length} MCP clients configured, ${installedSkills}/${status.skillTargets.length} skills installed.`;
|
|
946
|
+
const summary = `Optional agent integration status: ${configuredMcp}/${status.mcpClients.length} MCP clients configured, ${installedSkills}/${status.skillTargets.length} skills installed.`;
|
|
685
947
|
return createToolResult(summary, { ok: true, status });
|
|
686
948
|
}
|
|
687
949
|
|
|
@@ -697,11 +959,15 @@ export async function handleLogTool(args) {
|
|
|
697
959
|
normal: DEFAULT_CONSOLE_LIMIT,
|
|
698
960
|
deep: 100,
|
|
699
961
|
});
|
|
700
|
-
return callBridgeTool(
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
962
|
+
return callBridgeTool(
|
|
963
|
+
'log.tail',
|
|
964
|
+
{
|
|
965
|
+
limit: normalizedArgs.limit ?? DEFAULT_CONSOLE_LIMIT,
|
|
966
|
+
},
|
|
967
|
+
{
|
|
968
|
+
tokenBudget: getToolTokenBudget(normalizedArgs),
|
|
969
|
+
}
|
|
970
|
+
);
|
|
705
971
|
}
|
|
706
972
|
|
|
707
973
|
/**
|
|
@@ -711,7 +977,10 @@ export async function handleLogTool(args) {
|
|
|
711
977
|
*/
|
|
712
978
|
export async function handleHealthTool() {
|
|
713
979
|
return withToolClient(async (client) => {
|
|
714
|
-
const response = await client.request({
|
|
980
|
+
const response = await client.request({
|
|
981
|
+
method: 'health.ping',
|
|
982
|
+
meta: { source: REQUEST_SOURCE },
|
|
983
|
+
});
|
|
715
984
|
return summarizeToolResponse(response, 'health.ping');
|
|
716
985
|
});
|
|
717
986
|
}
|
|
@@ -727,75 +996,87 @@ export async function handleBatchTool(args) {
|
|
|
727
996
|
|
|
728
997
|
const calls = args.calls;
|
|
729
998
|
return withToolClient(async (client) => {
|
|
730
|
-
const results = await Promise.all(
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
999
|
+
const results = await Promise.all(
|
|
1000
|
+
calls.map(async (call) => {
|
|
1001
|
+
if (!call || typeof call !== 'object' || typeof call.method !== 'string') {
|
|
1002
|
+
return {
|
|
1003
|
+
method: '',
|
|
1004
|
+
tabId: null,
|
|
1005
|
+
ok: false,
|
|
1006
|
+
summary: 'INVALID_REQUEST: Each batch call needs a method.',
|
|
1007
|
+
evidence: null,
|
|
1008
|
+
error: {
|
|
1009
|
+
code: 'INVALID_REQUEST',
|
|
1010
|
+
message: 'Each batch call needs a method.',
|
|
1011
|
+
},
|
|
1012
|
+
response: null,
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
742
1015
|
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
1016
|
+
if (!METHOD_SET.has(/** @type {BridgeMethod} */ (call.method))) {
|
|
1017
|
+
return {
|
|
1018
|
+
method: call.method,
|
|
1019
|
+
tabId: null,
|
|
1020
|
+
ok: false,
|
|
1021
|
+
summary: `INVALID_REQUEST: Unknown bridge method "${call.method}".`,
|
|
1022
|
+
evidence: null,
|
|
1023
|
+
error: {
|
|
1024
|
+
code: 'INVALID_REQUEST',
|
|
1025
|
+
message: `Unknown bridge method "${call.method}".`,
|
|
1026
|
+
},
|
|
1027
|
+
response: null,
|
|
1028
|
+
};
|
|
1029
|
+
}
|
|
757
1030
|
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
1031
|
+
const method = /** @type {BridgeMethod} */ (call.method);
|
|
1032
|
+
const tabId = bridgeMethodNeedsTab(method)
|
|
1033
|
+
? typeof call.tabId === 'number'
|
|
1034
|
+
? call.tabId
|
|
1035
|
+
: null
|
|
1036
|
+
: null;
|
|
1037
|
+
const tokenBudget = getToolTokenBudget(call);
|
|
763
1038
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
1039
|
+
const startTime = Date.now();
|
|
1040
|
+
try {
|
|
1041
|
+
const response = await client.request({
|
|
1042
|
+
method,
|
|
1043
|
+
params: call.params || {},
|
|
1044
|
+
tabId,
|
|
1045
|
+
meta: {
|
|
1046
|
+
source: REQUEST_SOURCE,
|
|
1047
|
+
...(tokenBudget != null ? { token_budget: tokenBudget } : {}),
|
|
1048
|
+
},
|
|
1049
|
+
});
|
|
1050
|
+
return summarizeBatchResponseItem({
|
|
1051
|
+
method,
|
|
1052
|
+
tabId,
|
|
1053
|
+
response,
|
|
1054
|
+
durationMs: Date.now() - startTime,
|
|
1055
|
+
});
|
|
1056
|
+
} catch (error) {
|
|
1057
|
+
return summarizeBatchErrorItem({
|
|
1058
|
+
method,
|
|
1059
|
+
tabId,
|
|
1060
|
+
error,
|
|
1061
|
+
durationMs: Date.now() - startTime,
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
})
|
|
1065
|
+
);
|
|
790
1066
|
|
|
791
1067
|
const failureCount = results.filter((result) => !result.ok).length;
|
|
792
|
-
const summary =
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
1068
|
+
const summary =
|
|
1069
|
+
failureCount === 0
|
|
1070
|
+
? `Batch executed ${results.length} call(s).`
|
|
1071
|
+
: `Batch executed ${results.length} call(s) with ${failureCount} error(s).`;
|
|
1072
|
+
return createToolResult(
|
|
1073
|
+
summary,
|
|
1074
|
+
{
|
|
1075
|
+
ok: failureCount === 0,
|
|
1076
|
+
results,
|
|
1077
|
+
},
|
|
1078
|
+
failureCount > 0
|
|
1079
|
+
);
|
|
799
1080
|
});
|
|
800
1081
|
}
|
|
801
1082
|
|
|
@@ -804,7 +1085,7 @@ export async function handleBatchTool(args) {
|
|
|
804
1085
|
* @returns {Promise<ToolResult>}
|
|
805
1086
|
*/
|
|
806
1087
|
export async function handleRawCallTool(args) {
|
|
807
|
-
if (!
|
|
1088
|
+
if (!METHOD_SET.has(/** @type {BridgeMethod} */ (args.method))) {
|
|
808
1089
|
return summarizeToolError(`Unknown bridge method "${args.method}".`);
|
|
809
1090
|
}
|
|
810
1091
|
|
|
@@ -815,21 +1096,25 @@ export async function handleRawCallTool(args) {
|
|
|
815
1096
|
args.params || {},
|
|
816
1097
|
{
|
|
817
1098
|
tabId: typeof args.tabId === 'number' ? args.tabId : null,
|
|
818
|
-
source: REQUEST_SOURCE
|
|
1099
|
+
source: REQUEST_SOURCE,
|
|
819
1100
|
}
|
|
820
1101
|
);
|
|
821
1102
|
|
|
822
1103
|
if (!response.ok) {
|
|
823
|
-
return createToolResult(
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
1104
|
+
return createToolResult(
|
|
1105
|
+
response.error.message,
|
|
1106
|
+
{
|
|
1107
|
+
ok: false,
|
|
1108
|
+
error: response.error,
|
|
1109
|
+
response,
|
|
1110
|
+
},
|
|
1111
|
+
true
|
|
1112
|
+
);
|
|
828
1113
|
}
|
|
829
1114
|
|
|
830
1115
|
return createToolResult(`Called ${args.method}.`, {
|
|
831
1116
|
ok: true,
|
|
832
|
-
response: response.result
|
|
1117
|
+
response: response.result,
|
|
833
1118
|
});
|
|
834
1119
|
});
|
|
835
1120
|
}
|
|
@@ -858,14 +1143,30 @@ const INVESTIGATE_SCOPES = {
|
|
|
858
1143
|
label: 'quick',
|
|
859
1144
|
steps: [
|
|
860
1145
|
{ method: 'page.get_state', params: () => ({}) },
|
|
861
|
-
{
|
|
1146
|
+
{
|
|
1147
|
+
method: 'dom.query',
|
|
1148
|
+
params: (a) => ({
|
|
1149
|
+
selector: a.selector || 'body',
|
|
1150
|
+
maxNodes: 10,
|
|
1151
|
+
maxDepth: 2,
|
|
1152
|
+
textBudget: 300,
|
|
1153
|
+
}),
|
|
1154
|
+
},
|
|
862
1155
|
],
|
|
863
1156
|
},
|
|
864
1157
|
normal: {
|
|
865
1158
|
label: 'normal',
|
|
866
1159
|
steps: [
|
|
867
1160
|
{ method: 'page.get_state', params: () => ({}) },
|
|
868
|
-
{
|
|
1161
|
+
{
|
|
1162
|
+
method: 'dom.query',
|
|
1163
|
+
params: (a) => ({
|
|
1164
|
+
selector: a.selector || 'body',
|
|
1165
|
+
maxNodes: 25,
|
|
1166
|
+
maxDepth: 4,
|
|
1167
|
+
textBudget: 600,
|
|
1168
|
+
}),
|
|
1169
|
+
},
|
|
869
1170
|
{ method: 'page.get_text', params: () => ({ textBudget: 4000 }) },
|
|
870
1171
|
],
|
|
871
1172
|
},
|
|
@@ -873,9 +1174,20 @@ const INVESTIGATE_SCOPES = {
|
|
|
873
1174
|
label: 'deep',
|
|
874
1175
|
steps: [
|
|
875
1176
|
{ method: 'page.get_state', params: () => ({}) },
|
|
876
|
-
{
|
|
1177
|
+
{
|
|
1178
|
+
method: 'dom.query',
|
|
1179
|
+
params: (a) => ({
|
|
1180
|
+
selector: a.selector || 'body',
|
|
1181
|
+
maxNodes: 50,
|
|
1182
|
+
maxDepth: 6,
|
|
1183
|
+
textBudget: 1000,
|
|
1184
|
+
}),
|
|
1185
|
+
},
|
|
877
1186
|
{ method: 'page.get_text', params: () => ({ textBudget: 8000 }) },
|
|
878
|
-
{
|
|
1187
|
+
{
|
|
1188
|
+
method: 'page.get_console',
|
|
1189
|
+
params: () => ({ level: 'warn', limit: 20 }),
|
|
1190
|
+
},
|
|
879
1191
|
{ method: 'page.get_network', params: () => ({ limit: 20 }) },
|
|
880
1192
|
],
|
|
881
1193
|
},
|
|
@@ -947,12 +1259,17 @@ export async function handleInvestigateTool(args) {
|
|
|
947
1259
|
? `Investigation complete (${scope.label}, ${stepResults.length} steps, ${totalDuration}ms). Objective: ${objective}`
|
|
948
1260
|
: `Investigation partial (${scope.label}, ${stepResults.length} steps, ${failedSteps.length} failed, ${totalDuration}ms). Objective: ${objective}`;
|
|
949
1261
|
|
|
950
|
-
return createToolResult(
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
1262
|
+
return createToolResult(
|
|
1263
|
+
summaryText,
|
|
1264
|
+
{
|
|
1265
|
+
ok: allOk,
|
|
1266
|
+
objective,
|
|
1267
|
+
scope: scopeName,
|
|
1268
|
+
heuristicFallback: true,
|
|
1269
|
+
steps: stepResults,
|
|
1270
|
+
failedSteps,
|
|
1271
|
+
},
|
|
1272
|
+
!allOk
|
|
1273
|
+
);
|
|
957
1274
|
});
|
|
958
1275
|
}
|