cdp-toolkit 1.10.0 → 2.0.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/CHANGELOG.md +60 -0
- package/README.md +61 -12
- package/dist/cli.js +1233 -312
- package/dist/index.js +11 -11
- package/dist/mcp.js +1314 -320
- package/package.json +4 -2
- package/src/bidi/driver.ts +219 -29
- package/src/bidi/launch.ts +51 -1
- package/src/bidi/marionette.ts +276 -0
- package/src/bidi/session-lease.ts +265 -0
- package/src/cli.ts +10 -0
- package/src/install/browser.ts +211 -0
- package/src/install/harness.ts +224 -0
- package/src/install/wizard.ts +412 -0
- package/src/manifest.ts +297 -297
- package/src/mcp.ts +123 -11
- package/src/toolDocs.ts +468 -0
- package/src/toolGroups.ts +49 -0
- package/src/tools/navigation.ts +4 -2
package/dist/mcp.js
CHANGED
|
@@ -5200,29 +5200,28 @@ var TOOLS = {
|
|
|
5200
5200
|
var TOOL_NAMES = Object.keys(TOOLS);
|
|
5201
5201
|
|
|
5202
5202
|
// src/mcp.ts
|
|
5203
|
-
import { Server } from "@modelcontextprotocol/
|
|
5204
|
-
import { StdioServerTransport } from "@modelcontextprotocol/
|
|
5205
|
-
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
5203
|
+
import { Server } from "@modelcontextprotocol/server";
|
|
5204
|
+
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
|
|
5206
5205
|
|
|
5207
5206
|
// src/manifest.ts
|
|
5208
5207
|
var MANIFEST = [
|
|
5209
5208
|
{
|
|
5210
5209
|
name: "list_pages",
|
|
5211
|
-
description: "
|
|
5210
|
+
description: "List browser page targets; optionally include non-page targets and probe responsiveness.",
|
|
5212
5211
|
inputSchema: {
|
|
5213
5212
|
type: "object",
|
|
5214
5213
|
properties: {
|
|
5215
5214
|
lease: {
|
|
5216
5215
|
type: "string",
|
|
5217
|
-
description: "Lease token
|
|
5216
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5218
5217
|
},
|
|
5219
5218
|
all: {
|
|
5220
5219
|
type: "boolean",
|
|
5221
|
-
description: "Include non-page targets
|
|
5220
|
+
description: "Include non-page targets."
|
|
5222
5221
|
},
|
|
5223
5222
|
probe: {
|
|
5224
5223
|
type: "boolean",
|
|
5225
|
-
description: "
|
|
5224
|
+
description: "Probe renderer responsiveness."
|
|
5226
5225
|
}
|
|
5227
5226
|
},
|
|
5228
5227
|
required: [],
|
|
@@ -5231,29 +5230,29 @@ var MANIFEST = [
|
|
|
5231
5230
|
},
|
|
5232
5231
|
{
|
|
5233
5232
|
name: "new_page",
|
|
5234
|
-
description: "Open a
|
|
5233
|
+
description: "Open a browser tab, optionally claim it; navigation is not awaited.",
|
|
5235
5234
|
inputSchema: {
|
|
5236
5235
|
type: "object",
|
|
5237
5236
|
properties: {
|
|
5238
5237
|
lease: {
|
|
5239
5238
|
type: "string",
|
|
5240
|
-
description: "Lease token
|
|
5239
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5241
5240
|
},
|
|
5242
5241
|
url: {
|
|
5243
5242
|
type: "string",
|
|
5244
|
-
description: "URL
|
|
5243
|
+
description: "URL value."
|
|
5245
5244
|
},
|
|
5246
5245
|
claim: {
|
|
5247
5246
|
type: "boolean",
|
|
5248
|
-
description: "Claim the new tab
|
|
5247
|
+
description: "Claim the new tab."
|
|
5249
5248
|
},
|
|
5250
5249
|
label: {
|
|
5251
5250
|
type: "string",
|
|
5252
|
-
description: "Agent
|
|
5251
|
+
description: "Agent lease label."
|
|
5253
5252
|
},
|
|
5254
5253
|
ttlMs: {
|
|
5255
5254
|
type: "number",
|
|
5256
|
-
description: "
|
|
5255
|
+
description: "Lease TTL in milliseconds."
|
|
5257
5256
|
}
|
|
5258
5257
|
},
|
|
5259
5258
|
required: [],
|
|
@@ -5262,17 +5261,17 @@ var MANIFEST = [
|
|
|
5262
5261
|
},
|
|
5263
5262
|
{
|
|
5264
5263
|
name: "close_page",
|
|
5265
|
-
description: "Close a page target
|
|
5264
|
+
description: "Close a selected page; target must resolve explicitly.",
|
|
5266
5265
|
inputSchema: {
|
|
5267
5266
|
type: "object",
|
|
5268
5267
|
properties: {
|
|
5269
5268
|
lease: {
|
|
5270
5269
|
type: "string",
|
|
5271
|
-
description: "Lease token
|
|
5270
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5272
5271
|
},
|
|
5273
5272
|
target: {
|
|
5274
5273
|
type: "string",
|
|
5275
|
-
description: "Page selector
|
|
5274
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5276
5275
|
}
|
|
5277
5276
|
},
|
|
5278
5277
|
required: [
|
|
@@ -5283,17 +5282,17 @@ var MANIFEST = [
|
|
|
5283
5282
|
},
|
|
5284
5283
|
{
|
|
5285
5284
|
name: "select_page",
|
|
5286
|
-
description: "
|
|
5285
|
+
description: "Focus a selected page and persist it as active; target must resolve explicitly.",
|
|
5287
5286
|
inputSchema: {
|
|
5288
5287
|
type: "object",
|
|
5289
5288
|
properties: {
|
|
5290
5289
|
lease: {
|
|
5291
5290
|
type: "string",
|
|
5292
|
-
description: "Lease token
|
|
5291
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5293
5292
|
},
|
|
5294
5293
|
target: {
|
|
5295
5294
|
type: "string",
|
|
5296
|
-
description: "Page selector
|
|
5295
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5297
5296
|
}
|
|
5298
5297
|
},
|
|
5299
5298
|
required: [
|
|
@@ -5304,25 +5303,25 @@ var MANIFEST = [
|
|
|
5304
5303
|
},
|
|
5305
5304
|
{
|
|
5306
5305
|
name: "navigate_page",
|
|
5307
|
-
description: "Navigate
|
|
5306
|
+
description: "Navigate, reload, or traverse page history; choose exactly one operation.",
|
|
5308
5307
|
inputSchema: {
|
|
5309
5308
|
type: "object",
|
|
5310
5309
|
properties: {
|
|
5311
5310
|
lease: {
|
|
5312
5311
|
type: "string",
|
|
5313
|
-
description: "Lease token
|
|
5312
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5314
5313
|
},
|
|
5315
5314
|
target: {
|
|
5316
5315
|
type: "string",
|
|
5317
|
-
description: "Page selector
|
|
5316
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5318
5317
|
},
|
|
5319
5318
|
url: {
|
|
5320
5319
|
type: "string",
|
|
5321
|
-
description: "
|
|
5320
|
+
description: "URL value."
|
|
5322
5321
|
},
|
|
5323
5322
|
reload: {
|
|
5324
5323
|
type: "boolean",
|
|
5325
|
-
description: "Reload
|
|
5324
|
+
description: "Reload before capture."
|
|
5326
5325
|
},
|
|
5327
5326
|
history: {
|
|
5328
5327
|
type: "string",
|
|
@@ -5330,11 +5329,11 @@ var MANIFEST = [
|
|
|
5330
5329
|
"back",
|
|
5331
5330
|
"forward"
|
|
5332
5331
|
],
|
|
5333
|
-
description: "
|
|
5332
|
+
description: "History direction."
|
|
5334
5333
|
},
|
|
5335
5334
|
ignoreCache: {
|
|
5336
5335
|
type: "boolean",
|
|
5337
|
-
description: "
|
|
5336
|
+
description: "Bypass cache on reload."
|
|
5338
5337
|
},
|
|
5339
5338
|
waitUntil: {
|
|
5340
5339
|
type: "string",
|
|
@@ -5342,11 +5341,11 @@ var MANIFEST = [
|
|
|
5342
5341
|
"load",
|
|
5343
5342
|
"domcontentloaded"
|
|
5344
5343
|
],
|
|
5345
|
-
description: "
|
|
5344
|
+
description: "Load milestone."
|
|
5346
5345
|
},
|
|
5347
5346
|
timeoutMs: {
|
|
5348
5347
|
type: "number",
|
|
5349
|
-
description: "
|
|
5348
|
+
description: "Timeout in milliseconds."
|
|
5350
5349
|
}
|
|
5351
5350
|
},
|
|
5352
5351
|
additionalProperties: false
|
|
@@ -5354,29 +5353,29 @@ var MANIFEST = [
|
|
|
5354
5353
|
},
|
|
5355
5354
|
{
|
|
5356
5355
|
name: "wait_for",
|
|
5357
|
-
description: "
|
|
5356
|
+
description: "Wait for a text substring in document.body.innerText; timeout throws.",
|
|
5358
5357
|
inputSchema: {
|
|
5359
5358
|
type: "object",
|
|
5360
5359
|
properties: {
|
|
5361
5360
|
lease: {
|
|
5362
5361
|
type: "string",
|
|
5363
|
-
description: "Lease token
|
|
5362
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5364
5363
|
},
|
|
5365
5364
|
target: {
|
|
5366
5365
|
type: "string",
|
|
5367
|
-
description: "Page selector
|
|
5366
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5368
5367
|
},
|
|
5369
5368
|
text: {
|
|
5370
5369
|
type: "string",
|
|
5371
|
-
description: "
|
|
5370
|
+
description: "Text substring."
|
|
5372
5371
|
},
|
|
5373
5372
|
timeoutMs: {
|
|
5374
5373
|
type: "number",
|
|
5375
|
-
description: "
|
|
5374
|
+
description: "Timeout in milliseconds."
|
|
5376
5375
|
},
|
|
5377
5376
|
pollMs: {
|
|
5378
5377
|
type: "number",
|
|
5379
|
-
description: "
|
|
5378
|
+
description: "Polling interval in milliseconds."
|
|
5380
5379
|
}
|
|
5381
5380
|
},
|
|
5382
5381
|
required: [
|
|
@@ -5387,37 +5386,37 @@ var MANIFEST = [
|
|
|
5387
5386
|
},
|
|
5388
5387
|
{
|
|
5389
5388
|
name: "evaluate_script",
|
|
5390
|
-
description: "
|
|
5389
|
+
description: "Evaluate JavaScript in a page or Chrome worker; args require a function literal.",
|
|
5391
5390
|
inputSchema: {
|
|
5392
5391
|
type: "object",
|
|
5393
5392
|
properties: {
|
|
5394
5393
|
lease: {
|
|
5395
5394
|
type: "string",
|
|
5396
|
-
description: "Lease token
|
|
5395
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5397
5396
|
},
|
|
5398
5397
|
target: {
|
|
5399
5398
|
type: "string",
|
|
5400
|
-
description: "Page selector
|
|
5399
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5401
5400
|
},
|
|
5402
5401
|
wake: {
|
|
5403
5402
|
type: "boolean",
|
|
5404
|
-
description: "
|
|
5403
|
+
description: "Wake worker before capture."
|
|
5405
5404
|
},
|
|
5406
5405
|
expression: {
|
|
5407
5406
|
type: "string",
|
|
5408
|
-
description: "JavaScript
|
|
5407
|
+
description: "JavaScript expression or function."
|
|
5409
5408
|
},
|
|
5410
5409
|
awaitPromise: {
|
|
5411
5410
|
type: "boolean",
|
|
5412
|
-
description: "Await
|
|
5411
|
+
description: "Await Promise results."
|
|
5413
5412
|
},
|
|
5414
5413
|
args: {
|
|
5415
5414
|
type: "array",
|
|
5416
|
-
description: "Positional JSON
|
|
5415
|
+
description: "Positional JSON arguments."
|
|
5417
5416
|
},
|
|
5418
5417
|
savePath: {
|
|
5419
5418
|
type: "string",
|
|
5420
|
-
description: "
|
|
5419
|
+
description: "Output file path."
|
|
5421
5420
|
}
|
|
5422
5421
|
},
|
|
5423
5422
|
required: [
|
|
@@ -5428,29 +5427,29 @@ var MANIFEST = [
|
|
|
5428
5427
|
},
|
|
5429
5428
|
{
|
|
5430
5429
|
name: "list_cookies",
|
|
5431
|
-
description: "Read
|
|
5430
|
+
description: "Read cookies for a selected page, including httpOnly values; savePath keeps values out of the response.",
|
|
5432
5431
|
inputSchema: {
|
|
5433
5432
|
type: "object",
|
|
5434
5433
|
properties: {
|
|
5435
5434
|
lease: {
|
|
5436
5435
|
type: "string",
|
|
5437
|
-
description: "Lease token
|
|
5436
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5438
5437
|
},
|
|
5439
5438
|
target: {
|
|
5440
5439
|
type: "string",
|
|
5441
|
-
description: "Page selector
|
|
5440
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5442
5441
|
},
|
|
5443
5442
|
domain: {
|
|
5444
5443
|
type: "string",
|
|
5445
|
-
description: "
|
|
5444
|
+
description: "Cookie domain."
|
|
5446
5445
|
},
|
|
5447
5446
|
name: {
|
|
5448
5447
|
type: "string",
|
|
5449
|
-
description: "
|
|
5448
|
+
description: "Cookie name."
|
|
5450
5449
|
},
|
|
5451
5450
|
savePath: {
|
|
5452
5451
|
type: "string",
|
|
5453
|
-
description: "
|
|
5452
|
+
description: "Output file path."
|
|
5454
5453
|
}
|
|
5455
5454
|
},
|
|
5456
5455
|
required: [],
|
|
@@ -5459,49 +5458,49 @@ var MANIFEST = [
|
|
|
5459
5458
|
},
|
|
5460
5459
|
{
|
|
5461
5460
|
name: "set_cookie",
|
|
5462
|
-
description: "
|
|
5461
|
+
description: "Set one page cookie, including httpOnly or secure flags; provide url or domain.",
|
|
5463
5462
|
inputSchema: {
|
|
5464
5463
|
type: "object",
|
|
5465
5464
|
properties: {
|
|
5466
5465
|
lease: {
|
|
5467
5466
|
type: "string",
|
|
5468
|
-
description: "Lease token
|
|
5467
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5469
5468
|
},
|
|
5470
5469
|
target: {
|
|
5471
5470
|
type: "string",
|
|
5472
|
-
description: "Page selector
|
|
5471
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5473
5472
|
},
|
|
5474
5473
|
name: {
|
|
5475
5474
|
type: "string",
|
|
5476
|
-
description: "Cookie name.
|
|
5475
|
+
description: "Cookie name."
|
|
5477
5476
|
},
|
|
5478
5477
|
value: {
|
|
5479
5478
|
type: "string",
|
|
5480
|
-
description: "Cookie value.
|
|
5479
|
+
description: "Cookie value."
|
|
5481
5480
|
},
|
|
5482
5481
|
url: {
|
|
5483
5482
|
type: "string",
|
|
5484
|
-
description: "URL
|
|
5483
|
+
description: "URL value."
|
|
5485
5484
|
},
|
|
5486
5485
|
domain: {
|
|
5487
5486
|
type: "string",
|
|
5488
|
-
description: "Cookie domain
|
|
5487
|
+
description: "Cookie domain."
|
|
5489
5488
|
},
|
|
5490
5489
|
path: {
|
|
5491
5490
|
type: "string",
|
|
5492
|
-
description: "Cookie path
|
|
5491
|
+
description: "Cookie path."
|
|
5493
5492
|
},
|
|
5494
5493
|
expires: {
|
|
5495
5494
|
type: "number",
|
|
5496
|
-
description: "Expiry
|
|
5495
|
+
description: "Expiry Unix time in seconds."
|
|
5497
5496
|
},
|
|
5498
5497
|
httpOnly: {
|
|
5499
5498
|
type: "boolean",
|
|
5500
|
-
description: "Set
|
|
5499
|
+
description: "Set HttpOnly flag."
|
|
5501
5500
|
},
|
|
5502
5501
|
secure: {
|
|
5503
5502
|
type: "boolean",
|
|
5504
|
-
description: "Set
|
|
5503
|
+
description: "Set Secure flag."
|
|
5505
5504
|
},
|
|
5506
5505
|
sameSite: {
|
|
5507
5506
|
type: "string",
|
|
@@ -5511,7 +5510,7 @@ var MANIFEST = [
|
|
|
5511
5510
|
"none",
|
|
5512
5511
|
"default"
|
|
5513
5512
|
],
|
|
5514
|
-
description: "SameSite attribute
|
|
5513
|
+
description: "SameSite attribute."
|
|
5515
5514
|
}
|
|
5516
5515
|
},
|
|
5517
5516
|
required: [
|
|
@@ -5523,33 +5522,33 @@ var MANIFEST = [
|
|
|
5523
5522
|
},
|
|
5524
5523
|
{
|
|
5525
5524
|
name: "delete_cookies",
|
|
5526
|
-
description: "Delete
|
|
5525
|
+
description: "Delete a named page cookie; provide name and url or domain.",
|
|
5527
5526
|
inputSchema: {
|
|
5528
5527
|
type: "object",
|
|
5529
5528
|
properties: {
|
|
5530
5529
|
lease: {
|
|
5531
5530
|
type: "string",
|
|
5532
|
-
description: "Lease token
|
|
5531
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5533
5532
|
},
|
|
5534
5533
|
target: {
|
|
5535
5534
|
type: "string",
|
|
5536
|
-
description: "Page selector
|
|
5535
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5537
5536
|
},
|
|
5538
5537
|
name: {
|
|
5539
5538
|
type: "string",
|
|
5540
|
-
description: "
|
|
5539
|
+
description: "Cookie name."
|
|
5541
5540
|
},
|
|
5542
5541
|
url: {
|
|
5543
5542
|
type: "string",
|
|
5544
|
-
description: "
|
|
5543
|
+
description: "URL value."
|
|
5545
5544
|
},
|
|
5546
5545
|
domain: {
|
|
5547
5546
|
type: "string",
|
|
5548
|
-
description: "
|
|
5547
|
+
description: "Cookie domain."
|
|
5549
5548
|
},
|
|
5550
5549
|
path: {
|
|
5551
5550
|
type: "string",
|
|
5552
|
-
description: "
|
|
5551
|
+
description: "Cookie path."
|
|
5553
5552
|
}
|
|
5554
5553
|
},
|
|
5555
5554
|
required: [
|
|
@@ -5560,21 +5559,21 @@ var MANIFEST = [
|
|
|
5560
5559
|
},
|
|
5561
5560
|
{
|
|
5562
5561
|
name: "take_snapshot",
|
|
5563
|
-
description: "
|
|
5562
|
+
description: "Capture the page accessibility tree with interaction UIDs.",
|
|
5564
5563
|
inputSchema: {
|
|
5565
5564
|
type: "object",
|
|
5566
5565
|
properties: {
|
|
5567
5566
|
lease: {
|
|
5568
5567
|
type: "string",
|
|
5569
|
-
description: "Lease token
|
|
5568
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5570
5569
|
},
|
|
5571
5570
|
target: {
|
|
5572
5571
|
type: "string",
|
|
5573
|
-
description: "Page selector
|
|
5572
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5574
5573
|
},
|
|
5575
5574
|
interactiveOnly: {
|
|
5576
5575
|
type: "boolean",
|
|
5577
|
-
description: "
|
|
5576
|
+
description: "Only interactive nodes."
|
|
5578
5577
|
}
|
|
5579
5578
|
},
|
|
5580
5579
|
required: [],
|
|
@@ -5583,25 +5582,25 @@ var MANIFEST = [
|
|
|
5583
5582
|
},
|
|
5584
5583
|
{
|
|
5585
5584
|
name: "click",
|
|
5586
|
-
description: "Click an element
|
|
5585
|
+
description: "Click an element by UID or CSS selector; provide exactly one.",
|
|
5587
5586
|
inputSchema: {
|
|
5588
5587
|
type: "object",
|
|
5589
5588
|
properties: {
|
|
5590
5589
|
lease: {
|
|
5591
5590
|
type: "string",
|
|
5592
|
-
description: "Lease token
|
|
5591
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5593
5592
|
},
|
|
5594
5593
|
target: {
|
|
5595
5594
|
type: "string",
|
|
5596
|
-
description: "Page selector
|
|
5595
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5597
5596
|
},
|
|
5598
5597
|
uid: {
|
|
5599
5598
|
type: "number",
|
|
5600
|
-
description: "
|
|
5599
|
+
description: "Element backendDOMNodeId."
|
|
5601
5600
|
},
|
|
5602
5601
|
selector: {
|
|
5603
5602
|
type: "string",
|
|
5604
|
-
description: "CSS selector
|
|
5603
|
+
description: "CSS selector."
|
|
5605
5604
|
},
|
|
5606
5605
|
button: {
|
|
5607
5606
|
type: "string",
|
|
@@ -5610,11 +5609,11 @@ var MANIFEST = [
|
|
|
5610
5609
|
"right",
|
|
5611
5610
|
"middle"
|
|
5612
5611
|
],
|
|
5613
|
-
description: "Mouse button
|
|
5612
|
+
description: "Mouse button."
|
|
5614
5613
|
},
|
|
5615
5614
|
clickCount: {
|
|
5616
5615
|
type: "number",
|
|
5617
|
-
description: "
|
|
5616
|
+
description: "Click count."
|
|
5618
5617
|
},
|
|
5619
5618
|
modifiers: {
|
|
5620
5619
|
type: "array",
|
|
@@ -5627,7 +5626,7 @@ var MANIFEST = [
|
|
|
5627
5626
|
"Shift"
|
|
5628
5627
|
]
|
|
5629
5628
|
},
|
|
5630
|
-
description: "Modifier keys
|
|
5629
|
+
description: "Modifier keys: Control|Ctrl|Shift|Alt|Meta|Cmd."
|
|
5631
5630
|
}
|
|
5632
5631
|
},
|
|
5633
5632
|
required: [],
|
|
@@ -5636,25 +5635,25 @@ var MANIFEST = [
|
|
|
5636
5635
|
},
|
|
5637
5636
|
{
|
|
5638
5637
|
name: "hover",
|
|
5639
|
-
description: "
|
|
5638
|
+
description: "Hover an element by UID or CSS selector; provide exactly one.",
|
|
5640
5639
|
inputSchema: {
|
|
5641
5640
|
type: "object",
|
|
5642
5641
|
properties: {
|
|
5643
5642
|
lease: {
|
|
5644
5643
|
type: "string",
|
|
5645
|
-
description: "Lease token
|
|
5644
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5646
5645
|
},
|
|
5647
5646
|
target: {
|
|
5648
5647
|
type: "string",
|
|
5649
|
-
description: "Page selector
|
|
5648
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5650
5649
|
},
|
|
5651
5650
|
uid: {
|
|
5652
5651
|
type: "number",
|
|
5653
|
-
description: "
|
|
5652
|
+
description: "Element backendDOMNodeId."
|
|
5654
5653
|
},
|
|
5655
5654
|
selector: {
|
|
5656
5655
|
type: "string",
|
|
5657
|
-
description: "CSS selector
|
|
5656
|
+
description: "CSS selector."
|
|
5658
5657
|
}
|
|
5659
5658
|
},
|
|
5660
5659
|
required: [],
|
|
@@ -5663,67 +5662,67 @@ var MANIFEST = [
|
|
|
5663
5662
|
},
|
|
5664
5663
|
{
|
|
5665
5664
|
name: "drag",
|
|
5666
|
-
description: "
|
|
5665
|
+
description: "Drag from an element to a destination or offset; html5 mode is Chrome-only.",
|
|
5667
5666
|
inputSchema: {
|
|
5668
5667
|
type: "object",
|
|
5669
5668
|
properties: {
|
|
5670
5669
|
lease: {
|
|
5671
5670
|
type: "string",
|
|
5672
|
-
description: "Lease token
|
|
5671
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5673
5672
|
},
|
|
5674
5673
|
target: {
|
|
5675
5674
|
type: "string",
|
|
5676
|
-
description: "Page selector
|
|
5675
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5677
5676
|
},
|
|
5678
5677
|
from: {
|
|
5679
5678
|
type: "object",
|
|
5680
|
-
description: "
|
|
5679
|
+
description: "Drag source.",
|
|
5681
5680
|
properties: {
|
|
5682
5681
|
uid: {
|
|
5683
5682
|
type: "number",
|
|
5684
|
-
description: "
|
|
5683
|
+
description: "Element backendDOMNodeId."
|
|
5685
5684
|
},
|
|
5686
5685
|
selector: {
|
|
5687
5686
|
type: "string",
|
|
5688
|
-
description: "CSS selector
|
|
5687
|
+
description: "CSS selector."
|
|
5689
5688
|
}
|
|
5690
5689
|
},
|
|
5691
5690
|
additionalProperties: false
|
|
5692
5691
|
},
|
|
5693
5692
|
to: {
|
|
5694
5693
|
type: "object",
|
|
5695
|
-
description: "
|
|
5694
|
+
description: "Drag destination.",
|
|
5696
5695
|
properties: {
|
|
5697
5696
|
uid: {
|
|
5698
5697
|
type: "number",
|
|
5699
|
-
description: "
|
|
5698
|
+
description: "Element backendDOMNodeId."
|
|
5700
5699
|
},
|
|
5701
5700
|
selector: {
|
|
5702
5701
|
type: "string",
|
|
5703
|
-
description: "CSS selector
|
|
5702
|
+
description: "CSS selector."
|
|
5704
5703
|
},
|
|
5705
5704
|
x: {
|
|
5706
5705
|
type: "number",
|
|
5707
|
-
description: "
|
|
5706
|
+
description: "Viewport x-coordinate."
|
|
5708
5707
|
},
|
|
5709
5708
|
y: {
|
|
5710
5709
|
type: "number",
|
|
5711
|
-
description: "
|
|
5710
|
+
description: "Viewport y-coordinate."
|
|
5712
5711
|
}
|
|
5713
5712
|
},
|
|
5714
5713
|
additionalProperties: false
|
|
5715
5714
|
},
|
|
5716
5715
|
by: {
|
|
5717
5716
|
type: "object",
|
|
5718
|
-
description: "
|
|
5717
|
+
description: "Drag offset.",
|
|
5719
5718
|
properties: {
|
|
5720
5719
|
dx: {
|
|
5721
5720
|
type: "number",
|
|
5722
|
-
description: "Horizontal offset
|
|
5721
|
+
description: "Horizontal drag offset."
|
|
5723
5722
|
},
|
|
5724
5723
|
dy: {
|
|
5725
5724
|
type: "number",
|
|
5726
|
-
description: "Vertical offset
|
|
5725
|
+
description: "Vertical drag offset."
|
|
5727
5726
|
}
|
|
5728
5727
|
},
|
|
5729
5728
|
additionalProperties: false
|
|
@@ -5734,11 +5733,11 @@ var MANIFEST = [
|
|
|
5734
5733
|
"mouse",
|
|
5735
5734
|
"html5"
|
|
5736
5735
|
],
|
|
5737
|
-
description: "
|
|
5736
|
+
description: "Drag mode."
|
|
5738
5737
|
},
|
|
5739
5738
|
steps: {
|
|
5740
5739
|
type: "number",
|
|
5741
|
-
description: "
|
|
5740
|
+
description: "Interpolation steps."
|
|
5742
5741
|
}
|
|
5743
5742
|
},
|
|
5744
5743
|
required: [
|
|
@@ -5749,41 +5748,41 @@ var MANIFEST = [
|
|
|
5749
5748
|
},
|
|
5750
5749
|
{
|
|
5751
5750
|
name: "scroll",
|
|
5752
|
-
description: "
|
|
5751
|
+
description: "Dispatch a wheel event at an element or coordinate anchor; provide deltaX or deltaY.",
|
|
5753
5752
|
inputSchema: {
|
|
5754
5753
|
type: "object",
|
|
5755
5754
|
properties: {
|
|
5756
5755
|
lease: {
|
|
5757
5756
|
type: "string",
|
|
5758
|
-
description: "Lease token
|
|
5757
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5759
5758
|
},
|
|
5760
5759
|
target: {
|
|
5761
5760
|
type: "string",
|
|
5762
|
-
description: "Page selector
|
|
5761
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5763
5762
|
},
|
|
5764
5763
|
uid: {
|
|
5765
5764
|
type: "number",
|
|
5766
|
-
description: "
|
|
5765
|
+
description: "Element backendDOMNodeId."
|
|
5767
5766
|
},
|
|
5768
5767
|
selector: {
|
|
5769
5768
|
type: "string",
|
|
5770
|
-
description: "CSS selector
|
|
5769
|
+
description: "CSS selector."
|
|
5771
5770
|
},
|
|
5772
5771
|
x: {
|
|
5773
5772
|
type: "number",
|
|
5774
|
-
description: "
|
|
5773
|
+
description: "Viewport x-coordinate."
|
|
5775
5774
|
},
|
|
5776
5775
|
y: {
|
|
5777
5776
|
type: "number",
|
|
5778
|
-
description: "
|
|
5777
|
+
description: "Viewport y-coordinate."
|
|
5779
5778
|
},
|
|
5780
5779
|
deltaX: {
|
|
5781
5780
|
type: "number",
|
|
5782
|
-
description: "Horizontal scroll delta
|
|
5781
|
+
description: "Horizontal scroll delta."
|
|
5783
5782
|
},
|
|
5784
5783
|
deltaY: {
|
|
5785
5784
|
type: "number",
|
|
5786
|
-
description: "Vertical scroll delta
|
|
5785
|
+
description: "Vertical scroll delta."
|
|
5787
5786
|
}
|
|
5788
5787
|
},
|
|
5789
5788
|
required: [],
|
|
@@ -5792,17 +5791,17 @@ var MANIFEST = [
|
|
|
5792
5791
|
},
|
|
5793
5792
|
{
|
|
5794
5793
|
name: "dispatch_mouse",
|
|
5795
|
-
description: "
|
|
5794
|
+
description: "Dispatch one raw mouse event at viewport coordinates; Chrome-only.",
|
|
5796
5795
|
inputSchema: {
|
|
5797
5796
|
type: "object",
|
|
5798
5797
|
properties: {
|
|
5799
5798
|
lease: {
|
|
5800
5799
|
type: "string",
|
|
5801
|
-
description: "Lease token
|
|
5800
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5802
5801
|
},
|
|
5803
5802
|
target: {
|
|
5804
5803
|
type: "string",
|
|
5805
|
-
description: "Page selector
|
|
5804
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5806
5805
|
},
|
|
5807
5806
|
action: {
|
|
5808
5807
|
type: "string",
|
|
@@ -5811,15 +5810,15 @@ var MANIFEST = [
|
|
|
5811
5810
|
"down",
|
|
5812
5811
|
"up"
|
|
5813
5812
|
],
|
|
5814
|
-
description: "
|
|
5813
|
+
description: "Mouse action."
|
|
5815
5814
|
},
|
|
5816
5815
|
x: {
|
|
5817
5816
|
type: "number",
|
|
5818
|
-
description: "Viewport x-coordinate.
|
|
5817
|
+
description: "Viewport x-coordinate."
|
|
5819
5818
|
},
|
|
5820
5819
|
y: {
|
|
5821
5820
|
type: "number",
|
|
5822
|
-
description: "Viewport y-coordinate.
|
|
5821
|
+
description: "Viewport y-coordinate."
|
|
5823
5822
|
},
|
|
5824
5823
|
button: {
|
|
5825
5824
|
type: "string",
|
|
@@ -5828,11 +5827,11 @@ var MANIFEST = [
|
|
|
5828
5827
|
"right",
|
|
5829
5828
|
"middle"
|
|
5830
5829
|
],
|
|
5831
|
-
description: "Mouse button
|
|
5830
|
+
description: "Mouse button."
|
|
5832
5831
|
},
|
|
5833
5832
|
clickCount: {
|
|
5834
5833
|
type: "number",
|
|
5835
|
-
description: "Click
|
|
5834
|
+
description: "Click count."
|
|
5836
5835
|
},
|
|
5837
5836
|
modifiers: {
|
|
5838
5837
|
type: "array",
|
|
@@ -5845,7 +5844,7 @@ var MANIFEST = [
|
|
|
5845
5844
|
"Shift"
|
|
5846
5845
|
]
|
|
5847
5846
|
},
|
|
5848
|
-
description: "Modifier keys
|
|
5847
|
+
description: "Modifier keys: Control|Ctrl|Shift|Alt|Meta|Cmd."
|
|
5849
5848
|
}
|
|
5850
5849
|
},
|
|
5851
5850
|
required: [
|
|
@@ -5858,25 +5857,25 @@ var MANIFEST = [
|
|
|
5858
5857
|
},
|
|
5859
5858
|
{
|
|
5860
5859
|
name: "wait_for_download",
|
|
5861
|
-
description: "
|
|
5860
|
+
description: "Arm or collect a browser download; arm capture before triggering the download.",
|
|
5862
5861
|
inputSchema: {
|
|
5863
5862
|
type: "object",
|
|
5864
5863
|
properties: {
|
|
5865
5864
|
lease: {
|
|
5866
5865
|
type: "string",
|
|
5867
|
-
description: "Lease token
|
|
5866
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5868
5867
|
},
|
|
5869
5868
|
target: {
|
|
5870
5869
|
type: "string",
|
|
5871
|
-
description: "
|
|
5870
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5872
5871
|
},
|
|
5873
5872
|
arm: {
|
|
5874
5873
|
type: "boolean",
|
|
5875
|
-
description: "Arm download capture
|
|
5874
|
+
description: "Arm download capture."
|
|
5876
5875
|
},
|
|
5877
5876
|
timeoutMs: {
|
|
5878
5877
|
type: "number",
|
|
5879
|
-
description: "
|
|
5878
|
+
description: "Timeout in milliseconds."
|
|
5880
5879
|
}
|
|
5881
5880
|
},
|
|
5882
5881
|
required: [],
|
|
@@ -5885,32 +5884,32 @@ var MANIFEST = [
|
|
|
5885
5884
|
},
|
|
5886
5885
|
{
|
|
5887
5886
|
name: "grant_permissions",
|
|
5888
|
-
description: "Grant
|
|
5887
|
+
description: "Grant or reset browser permissions; permissions are origin-scoped and Chrome-only.",
|
|
5889
5888
|
inputSchema: {
|
|
5890
5889
|
type: "object",
|
|
5891
5890
|
properties: {
|
|
5892
5891
|
lease: {
|
|
5893
5892
|
type: "string",
|
|
5894
|
-
description: "Lease token
|
|
5893
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5895
5894
|
},
|
|
5896
5895
|
target: {
|
|
5897
5896
|
type: "string",
|
|
5898
|
-
description: "
|
|
5897
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5899
5898
|
},
|
|
5900
5899
|
permissions: {
|
|
5901
5900
|
type: "array",
|
|
5902
5901
|
items: {
|
|
5903
5902
|
type: "string"
|
|
5904
5903
|
},
|
|
5905
|
-
description: "CDP PermissionType values
|
|
5904
|
+
description: "CDP PermissionType values, e.g. geolocation|notifications|clipboardReadWrite."
|
|
5906
5905
|
},
|
|
5907
5906
|
origin: {
|
|
5908
5907
|
type: "string",
|
|
5909
|
-
description: "
|
|
5908
|
+
description: "Permission origin."
|
|
5910
5909
|
},
|
|
5911
5910
|
reset: {
|
|
5912
5911
|
type: "boolean",
|
|
5913
|
-
description: "
|
|
5912
|
+
description: "Reset permission grants."
|
|
5914
5913
|
}
|
|
5915
5914
|
},
|
|
5916
5915
|
required: [],
|
|
@@ -5919,25 +5918,25 @@ var MANIFEST = [
|
|
|
5919
5918
|
},
|
|
5920
5919
|
{
|
|
5921
5920
|
name: "fill",
|
|
5922
|
-
description: "
|
|
5921
|
+
description: "Replace an element contents; provide exactly one of UID or selector.",
|
|
5923
5922
|
inputSchema: {
|
|
5924
5923
|
type: "object",
|
|
5925
5924
|
properties: {
|
|
5926
5925
|
lease: {
|
|
5927
5926
|
type: "string",
|
|
5928
|
-
description: "Lease token
|
|
5927
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5929
5928
|
},
|
|
5930
5929
|
target: {
|
|
5931
5930
|
type: "string",
|
|
5932
|
-
description: "Page selector
|
|
5931
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5933
5932
|
},
|
|
5934
5933
|
uid: {
|
|
5935
5934
|
type: "number",
|
|
5936
|
-
description: "
|
|
5935
|
+
description: "Element backendDOMNodeId."
|
|
5937
5936
|
},
|
|
5938
5937
|
selector: {
|
|
5939
5938
|
type: "string",
|
|
5940
|
-
description: "CSS selector
|
|
5939
|
+
description: "CSS selector."
|
|
5941
5940
|
},
|
|
5942
5941
|
value: {
|
|
5943
5942
|
type: "string",
|
|
@@ -5952,35 +5951,35 @@ var MANIFEST = [
|
|
|
5952
5951
|
},
|
|
5953
5952
|
{
|
|
5954
5953
|
name: "fill_form",
|
|
5955
|
-
description: "
|
|
5954
|
+
description: "Fill multiple elements atomically; each field needs a UID or selector.",
|
|
5956
5955
|
inputSchema: {
|
|
5957
5956
|
type: "object",
|
|
5958
5957
|
properties: {
|
|
5959
5958
|
lease: {
|
|
5960
5959
|
type: "string",
|
|
5961
|
-
description: "Lease token
|
|
5960
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
5962
5961
|
},
|
|
5963
5962
|
target: {
|
|
5964
5963
|
type: "string",
|
|
5965
|
-
description: "Page selector
|
|
5964
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
5966
5965
|
},
|
|
5967
5966
|
fields: {
|
|
5968
5967
|
type: "array",
|
|
5969
|
-
description: "
|
|
5968
|
+
description: "Form fields to fill.",
|
|
5970
5969
|
items: {
|
|
5971
5970
|
type: "object",
|
|
5972
5971
|
properties: {
|
|
5973
5972
|
uid: {
|
|
5974
5973
|
type: "number",
|
|
5975
|
-
description: "
|
|
5974
|
+
description: "Element backendDOMNodeId."
|
|
5976
5975
|
},
|
|
5977
5976
|
selector: {
|
|
5978
5977
|
type: "string",
|
|
5979
|
-
description: "CSS selector
|
|
5978
|
+
description: "CSS selector."
|
|
5980
5979
|
},
|
|
5981
5980
|
value: {
|
|
5982
5981
|
type: "string",
|
|
5983
|
-
description: "
|
|
5982
|
+
description: "Text value to set; the field is cleared first, overwriting existing content."
|
|
5984
5983
|
}
|
|
5985
5984
|
},
|
|
5986
5985
|
required: [
|
|
@@ -5998,29 +5997,29 @@ var MANIFEST = [
|
|
|
5998
5997
|
},
|
|
5999
5998
|
{
|
|
6000
5999
|
name: "type_text",
|
|
6001
|
-
description: "
|
|
6000
|
+
description: "Append text to an element; input is atomic and does not clear existing content.",
|
|
6002
6001
|
inputSchema: {
|
|
6003
6002
|
type: "object",
|
|
6004
6003
|
properties: {
|
|
6005
6004
|
lease: {
|
|
6006
6005
|
type: "string",
|
|
6007
|
-
description: "Lease token
|
|
6006
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6008
6007
|
},
|
|
6009
6008
|
target: {
|
|
6010
6009
|
type: "string",
|
|
6011
|
-
description: "Page selector
|
|
6010
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6012
6011
|
},
|
|
6013
6012
|
uid: {
|
|
6014
6013
|
type: "number",
|
|
6015
|
-
description: "
|
|
6014
|
+
description: "Element backendDOMNodeId."
|
|
6016
6015
|
},
|
|
6017
6016
|
selector: {
|
|
6018
6017
|
type: "string",
|
|
6019
|
-
description: "CSS selector
|
|
6018
|
+
description: "CSS selector."
|
|
6020
6019
|
},
|
|
6021
6020
|
text: {
|
|
6022
6021
|
type: "string",
|
|
6023
|
-
description: "Text
|
|
6022
|
+
description: "Text substring."
|
|
6024
6023
|
}
|
|
6025
6024
|
},
|
|
6026
6025
|
required: [
|
|
@@ -6031,25 +6030,25 @@ var MANIFEST = [
|
|
|
6031
6030
|
},
|
|
6032
6031
|
{
|
|
6033
6032
|
name: "press_key",
|
|
6034
|
-
description: "
|
|
6033
|
+
description: "Press one named key or printable character with modifiers; no F-keys or IME.",
|
|
6035
6034
|
inputSchema: {
|
|
6036
6035
|
type: "object",
|
|
6037
6036
|
properties: {
|
|
6038
6037
|
lease: {
|
|
6039
6038
|
type: "string",
|
|
6040
|
-
description: "Lease token
|
|
6039
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6041
6040
|
},
|
|
6042
6041
|
target: {
|
|
6043
6042
|
type: "string",
|
|
6044
|
-
description: "Page selector
|
|
6043
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6045
6044
|
},
|
|
6046
6045
|
key: {
|
|
6047
6046
|
type: "string",
|
|
6048
|
-
description: "
|
|
6047
|
+
description: "Named key or printable character; e.g. Enter|Tab|Escape|ArrowDown|Backspace."
|
|
6049
6048
|
},
|
|
6050
6049
|
modifiers: {
|
|
6051
6050
|
type: "array",
|
|
6052
|
-
description: "Modifier
|
|
6051
|
+
description: "Modifier keys: Control|Ctrl|Shift|Alt|Meta|Cmd.",
|
|
6053
6052
|
items: {
|
|
6054
6053
|
type: "string"
|
|
6055
6054
|
}
|
|
@@ -6063,32 +6062,32 @@ var MANIFEST = [
|
|
|
6063
6062
|
},
|
|
6064
6063
|
{
|
|
6065
6064
|
name: "upload_file",
|
|
6066
|
-
description: "
|
|
6065
|
+
description: "Attach absolute file paths to a file input; provide an array.",
|
|
6067
6066
|
inputSchema: {
|
|
6068
6067
|
type: "object",
|
|
6069
6068
|
properties: {
|
|
6070
6069
|
lease: {
|
|
6071
6070
|
type: "string",
|
|
6072
|
-
description: "Lease token
|
|
6071
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6073
6072
|
},
|
|
6074
6073
|
target: {
|
|
6075
6074
|
type: "string",
|
|
6076
|
-
description: "Page selector
|
|
6075
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6077
6076
|
},
|
|
6078
6077
|
uid: {
|
|
6079
6078
|
type: "number",
|
|
6080
|
-
description: "
|
|
6079
|
+
description: "Element backendDOMNodeId."
|
|
6081
6080
|
},
|
|
6082
6081
|
selector: {
|
|
6083
6082
|
type: "string",
|
|
6084
|
-
description: "CSS selector
|
|
6083
|
+
description: "CSS selector."
|
|
6085
6084
|
},
|
|
6086
6085
|
files: {
|
|
6087
6086
|
type: "array",
|
|
6088
6087
|
items: {
|
|
6089
6088
|
type: "string"
|
|
6090
6089
|
},
|
|
6091
|
-
description:
|
|
6090
|
+
description: "Absolute file paths."
|
|
6092
6091
|
}
|
|
6093
6092
|
},
|
|
6094
6093
|
required: [
|
|
@@ -6099,17 +6098,17 @@ var MANIFEST = [
|
|
|
6099
6098
|
},
|
|
6100
6099
|
{
|
|
6101
6100
|
name: "take_screenshot",
|
|
6102
|
-
description: "
|
|
6101
|
+
description: "Capture a viewport, full page, or element to PNG/JPEG; oversized captures may be tiled.",
|
|
6103
6102
|
inputSchema: {
|
|
6104
6103
|
type: "object",
|
|
6105
6104
|
properties: {
|
|
6106
6105
|
lease: {
|
|
6107
6106
|
type: "string",
|
|
6108
|
-
description: "Lease token
|
|
6107
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6109
6108
|
},
|
|
6110
6109
|
target: {
|
|
6111
6110
|
type: "string",
|
|
6112
|
-
description: "Page selector
|
|
6111
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6113
6112
|
},
|
|
6114
6113
|
format: {
|
|
6115
6114
|
type: "string",
|
|
@@ -6117,47 +6116,47 @@ var MANIFEST = [
|
|
|
6117
6116
|
"png",
|
|
6118
6117
|
"jpeg"
|
|
6119
6118
|
],
|
|
6120
|
-
description: "Image format
|
|
6119
|
+
description: "Image/frame format."
|
|
6121
6120
|
},
|
|
6122
6121
|
quality: {
|
|
6123
6122
|
type: "number",
|
|
6124
|
-
description: "JPEG quality 0-100
|
|
6123
|
+
description: "JPEG quality 0-100."
|
|
6125
6124
|
},
|
|
6126
6125
|
fullPage: {
|
|
6127
6126
|
type: "boolean",
|
|
6128
|
-
description: "Capture
|
|
6127
|
+
description: "Capture full scrollable page."
|
|
6129
6128
|
},
|
|
6130
6129
|
scale: {
|
|
6131
6130
|
type: "number",
|
|
6132
|
-
description: "Output
|
|
6131
|
+
description: "Output scale (0<scale<=8)."
|
|
6133
6132
|
},
|
|
6134
6133
|
renderWidth: {
|
|
6135
6134
|
type: "number",
|
|
6136
|
-
description: "
|
|
6135
|
+
description: "Rendered viewport width."
|
|
6137
6136
|
},
|
|
6138
6137
|
renderHeight: {
|
|
6139
6138
|
type: "number",
|
|
6140
|
-
description: "
|
|
6139
|
+
description: "Rendered viewport height."
|
|
6141
6140
|
},
|
|
6142
6141
|
tile: {
|
|
6143
6142
|
type: "boolean",
|
|
6144
|
-
description: "
|
|
6143
|
+
description: "Vertical-band stitching."
|
|
6145
6144
|
},
|
|
6146
6145
|
uid: {
|
|
6147
6146
|
type: "number",
|
|
6148
|
-
description: "Element
|
|
6147
|
+
description: "Element backendDOMNodeId."
|
|
6149
6148
|
},
|
|
6150
6149
|
selector: {
|
|
6151
6150
|
type: "string",
|
|
6152
|
-
description: "CSS selector
|
|
6151
|
+
description: "CSS selector."
|
|
6153
6152
|
},
|
|
6154
6153
|
savePath: {
|
|
6155
6154
|
type: "string",
|
|
6156
|
-
description: "
|
|
6155
|
+
description: "Output file path."
|
|
6157
6156
|
},
|
|
6158
6157
|
returnBase64: {
|
|
6159
6158
|
type: "boolean",
|
|
6160
|
-
description: "
|
|
6159
|
+
description: "Return base64 bytes."
|
|
6161
6160
|
}
|
|
6162
6161
|
},
|
|
6163
6162
|
required: [],
|
|
@@ -6166,49 +6165,49 @@ var MANIFEST = [
|
|
|
6166
6165
|
},
|
|
6167
6166
|
{
|
|
6168
6167
|
name: "emulate",
|
|
6169
|
-
description: "
|
|
6168
|
+
description: "Apply browser emulation overrides; width and height must be paired.",
|
|
6170
6169
|
inputSchema: {
|
|
6171
6170
|
type: "object",
|
|
6172
6171
|
properties: {
|
|
6173
6172
|
lease: {
|
|
6174
6173
|
type: "string",
|
|
6175
|
-
description: "Lease token
|
|
6174
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6176
6175
|
},
|
|
6177
6176
|
target: {
|
|
6178
6177
|
type: "string",
|
|
6179
|
-
description: "Page selector
|
|
6178
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6180
6179
|
},
|
|
6181
6180
|
width: {
|
|
6182
6181
|
type: "number",
|
|
6183
|
-
description: "
|
|
6182
|
+
description: "Viewport width; pair with height."
|
|
6184
6183
|
},
|
|
6185
6184
|
height: {
|
|
6186
6185
|
type: "number",
|
|
6187
|
-
description: "
|
|
6186
|
+
description: "Viewport height; pair with width."
|
|
6188
6187
|
},
|
|
6189
6188
|
deviceScaleFactor: {
|
|
6190
6189
|
type: "number",
|
|
6191
|
-
description: "Device pixel ratio
|
|
6190
|
+
description: "Device pixel ratio."
|
|
6192
6191
|
},
|
|
6193
6192
|
mobile: {
|
|
6194
6193
|
type: "boolean",
|
|
6195
|
-
description: "
|
|
6194
|
+
description: "Mobile emulation."
|
|
6196
6195
|
},
|
|
6197
6196
|
userAgent: {
|
|
6198
6197
|
type: "string",
|
|
6199
|
-
description: "User-Agent
|
|
6198
|
+
description: "User-Agent override."
|
|
6200
6199
|
},
|
|
6201
6200
|
cpuThrottlingRate: {
|
|
6202
6201
|
type: "number",
|
|
6203
|
-
description: "CPU throttling
|
|
6202
|
+
description: "CPU throttling rate (>=1)."
|
|
6204
6203
|
},
|
|
6205
6204
|
media: {
|
|
6206
6205
|
type: "string",
|
|
6207
|
-
description: "
|
|
6206
|
+
description: "CSS media: screen|print|blank."
|
|
6208
6207
|
},
|
|
6209
6208
|
mediaFeatures: {
|
|
6210
6209
|
type: "array",
|
|
6211
|
-
description: "
|
|
6210
|
+
description: "CSS media feature overrides.",
|
|
6212
6211
|
items: {
|
|
6213
6212
|
type: "object",
|
|
6214
6213
|
properties: {
|
|
@@ -6218,7 +6217,7 @@ var MANIFEST = [
|
|
|
6218
6217
|
},
|
|
6219
6218
|
value: {
|
|
6220
6219
|
type: "string",
|
|
6221
|
-
description: "
|
|
6220
|
+
description: "Feature value, e.g. 'dark'."
|
|
6222
6221
|
}
|
|
6223
6222
|
},
|
|
6224
6223
|
required: [
|
|
@@ -6230,34 +6229,34 @@ var MANIFEST = [
|
|
|
6230
6229
|
},
|
|
6231
6230
|
networkConditions: {
|
|
6232
6231
|
type: "object",
|
|
6233
|
-
description: "Network overrides
|
|
6232
|
+
description: "Network condition overrides.",
|
|
6234
6233
|
properties: {
|
|
6235
6234
|
offline: {
|
|
6236
6235
|
type: "boolean",
|
|
6237
|
-
description: "
|
|
6236
|
+
description: "Simulate offline."
|
|
6238
6237
|
},
|
|
6239
6238
|
latency: {
|
|
6240
6239
|
type: "number",
|
|
6241
|
-
description: "
|
|
6240
|
+
description: "Network latency in milliseconds."
|
|
6242
6241
|
},
|
|
6243
6242
|
downloadThroughput: {
|
|
6244
6243
|
type: "number",
|
|
6245
|
-
description: "
|
|
6244
|
+
description: "Download throughput; -1 unlimited."
|
|
6246
6245
|
},
|
|
6247
6246
|
uploadThroughput: {
|
|
6248
6247
|
type: "number",
|
|
6249
|
-
description: "
|
|
6248
|
+
description: "Upload throughput; -1 unlimited."
|
|
6250
6249
|
},
|
|
6251
6250
|
connectionType: {
|
|
6252
6251
|
type: "string",
|
|
6253
|
-
description: "Connection
|
|
6252
|
+
description: "Connection: none|cellular2g|cellular3g|cellular4g|bluetooth|ethernet|wifi|wimax|other."
|
|
6254
6253
|
}
|
|
6255
6254
|
},
|
|
6256
6255
|
additionalProperties: false
|
|
6257
6256
|
},
|
|
6258
6257
|
clearOverrides: {
|
|
6259
6258
|
type: "boolean",
|
|
6260
|
-
description: "
|
|
6259
|
+
description: "Clear all emulation overrides."
|
|
6261
6260
|
}
|
|
6262
6261
|
},
|
|
6263
6262
|
required: [],
|
|
@@ -6266,33 +6265,33 @@ var MANIFEST = [
|
|
|
6266
6265
|
},
|
|
6267
6266
|
{
|
|
6268
6267
|
name: "resize_page",
|
|
6269
|
-
description: "
|
|
6268
|
+
description: "Set and verify page viewport metrics; width and height are required.",
|
|
6270
6269
|
inputSchema: {
|
|
6271
6270
|
type: "object",
|
|
6272
6271
|
properties: {
|
|
6273
6272
|
lease: {
|
|
6274
6273
|
type: "string",
|
|
6275
|
-
description: "Lease token
|
|
6274
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6276
6275
|
},
|
|
6277
6276
|
target: {
|
|
6278
6277
|
type: "string",
|
|
6279
|
-
description: "Page selector
|
|
6278
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6280
6279
|
},
|
|
6281
6280
|
width: {
|
|
6282
6281
|
type: "number",
|
|
6283
|
-
description: "Viewport width
|
|
6282
|
+
description: "Viewport width; pair with height."
|
|
6284
6283
|
},
|
|
6285
6284
|
height: {
|
|
6286
6285
|
type: "number",
|
|
6287
|
-
description: "Viewport height
|
|
6286
|
+
description: "Viewport height; pair with width."
|
|
6288
6287
|
},
|
|
6289
6288
|
deviceScaleFactor: {
|
|
6290
6289
|
type: "number",
|
|
6291
|
-
description: "Device pixel ratio
|
|
6290
|
+
description: "Device pixel ratio."
|
|
6292
6291
|
},
|
|
6293
6292
|
mobile: {
|
|
6294
6293
|
type: "boolean",
|
|
6295
|
-
description: "
|
|
6294
|
+
description: "Mobile emulation."
|
|
6296
6295
|
}
|
|
6297
6296
|
},
|
|
6298
6297
|
required: [
|
|
@@ -6304,33 +6303,33 @@ var MANIFEST = [
|
|
|
6304
6303
|
},
|
|
6305
6304
|
{
|
|
6306
6305
|
name: "handle_dialog",
|
|
6307
|
-
description: "
|
|
6306
|
+
description: "Handle the next JavaScript dialog; autoMs switches to timed multi-dialog mode.",
|
|
6308
6307
|
inputSchema: {
|
|
6309
6308
|
type: "object",
|
|
6310
6309
|
properties: {
|
|
6311
6310
|
lease: {
|
|
6312
6311
|
type: "string",
|
|
6313
|
-
description: "Lease token
|
|
6312
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6314
6313
|
},
|
|
6315
6314
|
target: {
|
|
6316
6315
|
type: "string",
|
|
6317
|
-
description: "Page selector
|
|
6316
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6318
6317
|
},
|
|
6319
6318
|
accept: {
|
|
6320
6319
|
type: "boolean",
|
|
6321
|
-
description: "
|
|
6320
|
+
description: "Accept or dismiss dialog."
|
|
6322
6321
|
},
|
|
6323
6322
|
promptText: {
|
|
6324
6323
|
type: "string",
|
|
6325
|
-
description: "
|
|
6324
|
+
description: "Prompt response text."
|
|
6326
6325
|
},
|
|
6327
6326
|
timeoutMs: {
|
|
6328
6327
|
type: "number",
|
|
6329
|
-
description: "
|
|
6328
|
+
description: "Timeout in milliseconds."
|
|
6330
6329
|
},
|
|
6331
6330
|
autoMs: {
|
|
6332
6331
|
type: "number",
|
|
6333
|
-
description: "
|
|
6332
|
+
description: "Multi-dialog window in milliseconds."
|
|
6334
6333
|
}
|
|
6335
6334
|
},
|
|
6336
6335
|
required: [
|
|
@@ -6341,29 +6340,29 @@ var MANIFEST = [
|
|
|
6341
6340
|
},
|
|
6342
6341
|
{
|
|
6343
6342
|
name: "list_console_messages",
|
|
6344
|
-
description: "Read
|
|
6343
|
+
description: "Read or recapture console messages for a page or worker; worker capture is Chrome-only.",
|
|
6345
6344
|
inputSchema: {
|
|
6346
6345
|
type: "object",
|
|
6347
6346
|
properties: {
|
|
6348
6347
|
lease: {
|
|
6349
6348
|
type: "string",
|
|
6350
|
-
description: "Lease token
|
|
6349
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6351
6350
|
},
|
|
6352
6351
|
target: {
|
|
6353
6352
|
type: "string",
|
|
6354
|
-
description: "Page selector
|
|
6353
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6355
6354
|
},
|
|
6356
6355
|
reload: {
|
|
6357
6356
|
type: "boolean",
|
|
6358
|
-
description: "
|
|
6357
|
+
description: "Reload before capture."
|
|
6359
6358
|
},
|
|
6360
6359
|
durationMs: {
|
|
6361
6360
|
type: "number",
|
|
6362
|
-
description: "Capture
|
|
6361
|
+
description: "Capture duration in milliseconds."
|
|
6363
6362
|
},
|
|
6364
6363
|
wake: {
|
|
6365
6364
|
type: "boolean",
|
|
6366
|
-
description: "
|
|
6365
|
+
description: "Wake worker before capture."
|
|
6367
6366
|
}
|
|
6368
6367
|
},
|
|
6369
6368
|
required: [],
|
|
@@ -6372,21 +6371,21 @@ var MANIFEST = [
|
|
|
6372
6371
|
},
|
|
6373
6372
|
{
|
|
6374
6373
|
name: "get_console_message",
|
|
6375
|
-
description: "Return one console entry by zero-based index from the
|
|
6374
|
+
description: "Return one console entry by zero-based index from the existing buffer.",
|
|
6376
6375
|
inputSchema: {
|
|
6377
6376
|
type: "object",
|
|
6378
6377
|
properties: {
|
|
6379
6378
|
lease: {
|
|
6380
6379
|
type: "string",
|
|
6381
|
-
description: "Lease token
|
|
6380
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6382
6381
|
},
|
|
6383
6382
|
target: {
|
|
6384
6383
|
type: "string",
|
|
6385
|
-
description: "Page selector
|
|
6384
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6386
6385
|
},
|
|
6387
6386
|
index: {
|
|
6388
6387
|
type: "number",
|
|
6389
|
-
description: "Zero-based index
|
|
6388
|
+
description: "Zero-based entry index."
|
|
6390
6389
|
}
|
|
6391
6390
|
},
|
|
6392
6391
|
required: [],
|
|
@@ -6395,33 +6394,33 @@ var MANIFEST = [
|
|
|
6395
6394
|
},
|
|
6396
6395
|
{
|
|
6397
6396
|
name: "list_network_requests",
|
|
6398
|
-
description: "
|
|
6397
|
+
description: "Read or recapture correlated network requests; worker capture is Chrome-only.",
|
|
6399
6398
|
inputSchema: {
|
|
6400
6399
|
type: "object",
|
|
6401
6400
|
properties: {
|
|
6402
6401
|
lease: {
|
|
6403
6402
|
type: "string",
|
|
6404
|
-
description: "Lease token
|
|
6403
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6405
6404
|
},
|
|
6406
6405
|
target: {
|
|
6407
6406
|
type: "string",
|
|
6408
|
-
description: "Page selector
|
|
6407
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6409
6408
|
},
|
|
6410
6409
|
reload: {
|
|
6411
6410
|
type: "boolean",
|
|
6412
|
-
description: "
|
|
6411
|
+
description: "Reload before capture."
|
|
6413
6412
|
},
|
|
6414
6413
|
durationMs: {
|
|
6415
6414
|
type: "number",
|
|
6416
|
-
description: "Capture
|
|
6415
|
+
description: "Capture duration in milliseconds."
|
|
6417
6416
|
},
|
|
6418
6417
|
filterUrl: {
|
|
6419
6418
|
type: "string",
|
|
6420
|
-
description: "
|
|
6419
|
+
description: "URL substring filter."
|
|
6421
6420
|
},
|
|
6422
6421
|
wake: {
|
|
6423
6422
|
type: "boolean",
|
|
6424
|
-
description: "
|
|
6423
|
+
description: "Wake worker before capture."
|
|
6425
6424
|
}
|
|
6426
6425
|
},
|
|
6427
6426
|
required: [],
|
|
@@ -6430,37 +6429,37 @@ var MANIFEST = [
|
|
|
6430
6429
|
},
|
|
6431
6430
|
{
|
|
6432
6431
|
name: "get_network_request",
|
|
6433
|
-
description: "Return
|
|
6432
|
+
description: "Return a network request by ID or URL; body capture requires URL.",
|
|
6434
6433
|
inputSchema: {
|
|
6435
6434
|
type: "object",
|
|
6436
6435
|
properties: {
|
|
6437
6436
|
lease: {
|
|
6438
6437
|
type: "string",
|
|
6439
|
-
description: "Lease token
|
|
6438
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6440
6439
|
},
|
|
6441
6440
|
target: {
|
|
6442
6441
|
type: "string",
|
|
6443
|
-
description: "Page selector
|
|
6442
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6444
6443
|
},
|
|
6445
6444
|
requestId: {
|
|
6446
6445
|
type: "string",
|
|
6447
|
-
description: "
|
|
6446
|
+
description: "Exact request ID."
|
|
6448
6447
|
},
|
|
6449
6448
|
url: {
|
|
6450
6449
|
type: "string",
|
|
6451
|
-
description: "
|
|
6450
|
+
description: "URL value."
|
|
6452
6451
|
},
|
|
6453
6452
|
includeBody: {
|
|
6454
6453
|
type: "boolean",
|
|
6455
|
-
description: "
|
|
6454
|
+
description: "Include response body."
|
|
6456
6455
|
},
|
|
6457
6456
|
durationMs: {
|
|
6458
6457
|
type: "number",
|
|
6459
|
-
description: "Capture
|
|
6458
|
+
description: "Capture duration in milliseconds."
|
|
6460
6459
|
},
|
|
6461
6460
|
wake: {
|
|
6462
6461
|
type: "boolean",
|
|
6463
|
-
description: "
|
|
6462
|
+
description: "Wake worker before capture."
|
|
6464
6463
|
}
|
|
6465
6464
|
},
|
|
6466
6465
|
required: [],
|
|
@@ -6469,24 +6468,24 @@ var MANIFEST = [
|
|
|
6469
6468
|
},
|
|
6470
6469
|
{
|
|
6471
6470
|
name: "performance_start_trace",
|
|
6472
|
-
description: "
|
|
6471
|
+
description: "Start an in-process trace; stop it from the same process.",
|
|
6473
6472
|
inputSchema: {
|
|
6474
6473
|
type: "object",
|
|
6475
6474
|
properties: {
|
|
6476
6475
|
lease: {
|
|
6477
6476
|
type: "string",
|
|
6478
|
-
description: "Lease token
|
|
6477
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6479
6478
|
},
|
|
6480
6479
|
target: {
|
|
6481
6480
|
type: "string",
|
|
6482
|
-
description: "Page selector
|
|
6481
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6483
6482
|
},
|
|
6484
6483
|
categories: {
|
|
6485
6484
|
type: "array",
|
|
6486
6485
|
items: {
|
|
6487
6486
|
type: "string"
|
|
6488
6487
|
},
|
|
6489
|
-
description: "Trace categories
|
|
6488
|
+
description: "Trace categories."
|
|
6490
6489
|
}
|
|
6491
6490
|
},
|
|
6492
6491
|
required: [],
|
|
@@ -6495,17 +6494,17 @@ var MANIFEST = [
|
|
|
6495
6494
|
},
|
|
6496
6495
|
{
|
|
6497
6496
|
name: "performance_stop_trace",
|
|
6498
|
-
description: "
|
|
6497
|
+
description: "Stop the in-process trace and write JSON; a live trace is required.",
|
|
6499
6498
|
inputSchema: {
|
|
6500
6499
|
type: "object",
|
|
6501
6500
|
properties: {
|
|
6502
6501
|
lease: {
|
|
6503
6502
|
type: "string",
|
|
6504
|
-
description: "Lease token
|
|
6503
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6505
6504
|
},
|
|
6506
6505
|
target: {
|
|
6507
6506
|
type: "string",
|
|
6508
|
-
description: "Page selector
|
|
6507
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6509
6508
|
}
|
|
6510
6509
|
},
|
|
6511
6510
|
required: [],
|
|
@@ -6514,17 +6513,17 @@ var MANIFEST = [
|
|
|
6514
6513
|
},
|
|
6515
6514
|
{
|
|
6516
6515
|
name: "performance_analyze_insight",
|
|
6517
|
-
description: "
|
|
6516
|
+
description: "Analyze a trace JSON file for key performance metrics; tracePath is required.",
|
|
6518
6517
|
inputSchema: {
|
|
6519
6518
|
type: "object",
|
|
6520
6519
|
properties: {
|
|
6521
6520
|
lease: {
|
|
6522
6521
|
type: "string",
|
|
6523
|
-
description: "Lease token
|
|
6522
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6524
6523
|
},
|
|
6525
6524
|
tracePath: {
|
|
6526
6525
|
type: "string",
|
|
6527
|
-
description: "
|
|
6526
|
+
description: "Trace JSON file path."
|
|
6528
6527
|
}
|
|
6529
6528
|
},
|
|
6530
6529
|
required: [],
|
|
@@ -6533,36 +6532,36 @@ var MANIFEST = [
|
|
|
6533
6532
|
},
|
|
6534
6533
|
{
|
|
6535
6534
|
name: "performance_trace",
|
|
6536
|
-
description: "
|
|
6535
|
+
description: "Run a one-shot trace with optional navigation and write JSON; durationMs controls capture time.",
|
|
6537
6536
|
inputSchema: {
|
|
6538
6537
|
type: "object",
|
|
6539
6538
|
properties: {
|
|
6540
6539
|
lease: {
|
|
6541
6540
|
type: "string",
|
|
6542
|
-
description: "Lease token
|
|
6541
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6543
6542
|
},
|
|
6544
6543
|
target: {
|
|
6545
6544
|
type: "string",
|
|
6546
|
-
description: "Page selector
|
|
6545
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6547
6546
|
},
|
|
6548
6547
|
durationMs: {
|
|
6549
6548
|
type: "number",
|
|
6550
|
-
description: "
|
|
6549
|
+
description: "Capture duration in milliseconds."
|
|
6551
6550
|
},
|
|
6552
6551
|
reload: {
|
|
6553
6552
|
type: "boolean",
|
|
6554
|
-
description: "Reload
|
|
6553
|
+
description: "Reload before capture."
|
|
6555
6554
|
},
|
|
6556
6555
|
navigateTo: {
|
|
6557
6556
|
type: "string",
|
|
6558
|
-
description: "
|
|
6557
|
+
description: "Navigation URL."
|
|
6559
6558
|
},
|
|
6560
6559
|
categories: {
|
|
6561
6560
|
type: "array",
|
|
6562
6561
|
items: {
|
|
6563
6562
|
type: "string"
|
|
6564
6563
|
},
|
|
6565
|
-
description: "Trace categories
|
|
6564
|
+
description: "Trace categories."
|
|
6566
6565
|
}
|
|
6567
6566
|
},
|
|
6568
6567
|
required: [],
|
|
@@ -6571,17 +6570,17 @@ var MANIFEST = [
|
|
|
6571
6570
|
},
|
|
6572
6571
|
{
|
|
6573
6572
|
name: "start_screen_recording",
|
|
6574
|
-
description: "
|
|
6573
|
+
description: "Start a tab screen recording; stop it from the same process.",
|
|
6575
6574
|
inputSchema: {
|
|
6576
6575
|
type: "object",
|
|
6577
6576
|
properties: {
|
|
6578
6577
|
lease: {
|
|
6579
6578
|
type: "string",
|
|
6580
|
-
description: "Lease token
|
|
6579
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6581
6580
|
},
|
|
6582
6581
|
target: {
|
|
6583
6582
|
type: "string",
|
|
6584
|
-
description: "Page selector
|
|
6583
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6585
6584
|
},
|
|
6586
6585
|
format: {
|
|
6587
6586
|
type: "string",
|
|
@@ -6589,27 +6588,27 @@ var MANIFEST = [
|
|
|
6589
6588
|
"jpeg",
|
|
6590
6589
|
"png"
|
|
6591
6590
|
],
|
|
6592
|
-
description: "
|
|
6591
|
+
description: "Image/frame format."
|
|
6593
6592
|
},
|
|
6594
6593
|
quality: {
|
|
6595
6594
|
type: "number",
|
|
6596
|
-
description: "JPEG
|
|
6595
|
+
description: "JPEG quality 0-100."
|
|
6597
6596
|
},
|
|
6598
6597
|
maxWidth: {
|
|
6599
6598
|
type: "number",
|
|
6600
|
-
description: "
|
|
6599
|
+
description: "Maximum frame width."
|
|
6601
6600
|
},
|
|
6602
6601
|
maxHeight: {
|
|
6603
6602
|
type: "number",
|
|
6604
|
-
description: "
|
|
6603
|
+
description: "Maximum frame height."
|
|
6605
6604
|
},
|
|
6606
6605
|
everyNthFrame: {
|
|
6607
6606
|
type: "number",
|
|
6608
|
-
description: "Capture
|
|
6607
|
+
description: "Capture every Nth frame."
|
|
6609
6608
|
},
|
|
6610
6609
|
bringToFront: {
|
|
6611
6610
|
type: "boolean",
|
|
6612
|
-
description: "Activate
|
|
6611
|
+
description: "Activate tab before recording."
|
|
6613
6612
|
}
|
|
6614
6613
|
},
|
|
6615
6614
|
required: [],
|
|
@@ -6618,21 +6617,21 @@ var MANIFEST = [
|
|
|
6618
6617
|
},
|
|
6619
6618
|
{
|
|
6620
6619
|
name: "stop_screen_recording",
|
|
6621
|
-
description: "
|
|
6620
|
+
description: "Stop a screen recording and encode MP4; target is required when multiple recordings exist.",
|
|
6622
6621
|
inputSchema: {
|
|
6623
6622
|
type: "object",
|
|
6624
6623
|
properties: {
|
|
6625
6624
|
lease: {
|
|
6626
6625
|
type: "string",
|
|
6627
|
-
description: "Lease token
|
|
6626
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6628
6627
|
},
|
|
6629
6628
|
target: {
|
|
6630
6629
|
type: "string",
|
|
6631
|
-
description: "
|
|
6630
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6632
6631
|
},
|
|
6633
6632
|
savePath: {
|
|
6634
6633
|
type: "string",
|
|
6635
|
-
description: "
|
|
6634
|
+
description: "Output file path."
|
|
6636
6635
|
}
|
|
6637
6636
|
},
|
|
6638
6637
|
required: [],
|
|
@@ -6641,21 +6640,21 @@ var MANIFEST = [
|
|
|
6641
6640
|
},
|
|
6642
6641
|
{
|
|
6643
6642
|
name: "take_heapsnapshot",
|
|
6644
|
-
description: "
|
|
6643
|
+
description: "Capture a V8 heap snapshot to JSON; the snapshot is not parsed.",
|
|
6645
6644
|
inputSchema: {
|
|
6646
6645
|
type: "object",
|
|
6647
6646
|
properties: {
|
|
6648
6647
|
lease: {
|
|
6649
6648
|
type: "string",
|
|
6650
|
-
description: "Lease token
|
|
6649
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6651
6650
|
},
|
|
6652
6651
|
target: {
|
|
6653
6652
|
type: "string",
|
|
6654
|
-
description: "Page selector
|
|
6653
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6655
6654
|
},
|
|
6656
6655
|
savePath: {
|
|
6657
6656
|
type: "string",
|
|
6658
|
-
description: "
|
|
6657
|
+
description: "Output file path."
|
|
6659
6658
|
}
|
|
6660
6659
|
},
|
|
6661
6660
|
required: [],
|
|
@@ -6664,28 +6663,28 @@ var MANIFEST = [
|
|
|
6664
6663
|
},
|
|
6665
6664
|
{
|
|
6666
6665
|
name: "lighthouse_audit",
|
|
6667
|
-
description: "
|
|
6666
|
+
description: "Run Lighthouse against a URL in its own tab; it does not audit a user tab.",
|
|
6668
6667
|
inputSchema: {
|
|
6669
6668
|
type: "object",
|
|
6670
6669
|
properties: {
|
|
6671
6670
|
lease: {
|
|
6672
6671
|
type: "string",
|
|
6673
|
-
description: "Lease token
|
|
6672
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6674
6673
|
},
|
|
6675
6674
|
url: {
|
|
6676
6675
|
type: "string",
|
|
6677
|
-
description: "
|
|
6676
|
+
description: "URL value."
|
|
6678
6677
|
},
|
|
6679
6678
|
categories: {
|
|
6680
6679
|
type: "array",
|
|
6681
6680
|
items: {
|
|
6682
6681
|
type: "string"
|
|
6683
6682
|
},
|
|
6684
|
-
description:
|
|
6683
|
+
description: "Lighthouse categories to run (--only-categories)."
|
|
6685
6684
|
},
|
|
6686
6685
|
savePath: {
|
|
6687
6686
|
type: "string",
|
|
6688
|
-
description: "
|
|
6687
|
+
description: "Output file path."
|
|
6689
6688
|
},
|
|
6690
6689
|
formFactor: {
|
|
6691
6690
|
type: "string",
|
|
@@ -6693,11 +6692,11 @@ var MANIFEST = [
|
|
|
6693
6692
|
"desktop",
|
|
6694
6693
|
"mobile"
|
|
6695
6694
|
],
|
|
6696
|
-
description:
|
|
6695
|
+
description: "Lighthouse form factor."
|
|
6697
6696
|
},
|
|
6698
6697
|
timeoutMs: {
|
|
6699
6698
|
type: "number",
|
|
6700
|
-
description: "
|
|
6699
|
+
description: "Timeout in milliseconds."
|
|
6701
6700
|
}
|
|
6702
6701
|
},
|
|
6703
6702
|
required: [
|
|
@@ -6708,21 +6707,21 @@ var MANIFEST = [
|
|
|
6708
6707
|
},
|
|
6709
6708
|
{
|
|
6710
6709
|
name: "mock_request",
|
|
6711
|
-
description: "Register a
|
|
6710
|
+
description: "Register a persistent request mock; urlPattern is required.",
|
|
6712
6711
|
inputSchema: {
|
|
6713
6712
|
type: "object",
|
|
6714
6713
|
properties: {
|
|
6715
6714
|
lease: {
|
|
6716
6715
|
type: "string",
|
|
6717
|
-
description: "Lease token
|
|
6716
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6718
6717
|
},
|
|
6719
6718
|
target: {
|
|
6720
6719
|
type: "string",
|
|
6721
|
-
description: "
|
|
6720
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6722
6721
|
},
|
|
6723
6722
|
urlPattern: {
|
|
6724
6723
|
type: "string",
|
|
6725
|
-
description:
|
|
6724
|
+
description: "URL glob (*, ?; \\ escapes)."
|
|
6726
6725
|
},
|
|
6727
6726
|
action: {
|
|
6728
6727
|
type: "string",
|
|
@@ -6735,39 +6734,39 @@ var MANIFEST = [
|
|
|
6735
6734
|
},
|
|
6736
6735
|
status: {
|
|
6737
6736
|
type: "number",
|
|
6738
|
-
description: "
|
|
6737
|
+
description: "Mock HTTP status."
|
|
6739
6738
|
},
|
|
6740
6739
|
body: {
|
|
6741
6740
|
type: "string",
|
|
6742
|
-
description: "
|
|
6741
|
+
description: "Mock response body."
|
|
6743
6742
|
},
|
|
6744
6743
|
contentType: {
|
|
6745
6744
|
type: "string",
|
|
6746
|
-
description:
|
|
6745
|
+
description: "Response Content-Type."
|
|
6747
6746
|
},
|
|
6748
6747
|
headers: {
|
|
6749
6748
|
type: "object",
|
|
6750
|
-
description:
|
|
6749
|
+
description: "Extra response headers."
|
|
6751
6750
|
},
|
|
6752
6751
|
errorReason: {
|
|
6753
6752
|
type: "string",
|
|
6754
|
-
description:
|
|
6753
|
+
description: "CDP Network.ErrorReason, e.g. Failed|BlockedByClient|ConnectionRefused|TimedOut."
|
|
6755
6754
|
},
|
|
6756
6755
|
method: {
|
|
6757
6756
|
type: "string",
|
|
6758
|
-
description:
|
|
6757
|
+
description: "HTTP method."
|
|
6759
6758
|
},
|
|
6760
6759
|
delayMs: {
|
|
6761
6760
|
type: "number",
|
|
6762
|
-
description: "
|
|
6761
|
+
description: "Artificial delay in milliseconds."
|
|
6763
6762
|
},
|
|
6764
6763
|
failRate: {
|
|
6765
6764
|
type: "number",
|
|
6766
|
-
description: "
|
|
6765
|
+
description: "Failure probability 0..1."
|
|
6767
6766
|
},
|
|
6768
6767
|
reload: {
|
|
6769
6768
|
type: "boolean",
|
|
6770
|
-
description: "Reload
|
|
6769
|
+
description: "Reload before capture."
|
|
6771
6770
|
}
|
|
6772
6771
|
},
|
|
6773
6772
|
required: [
|
|
@@ -6778,13 +6777,13 @@ var MANIFEST = [
|
|
|
6778
6777
|
},
|
|
6779
6778
|
{
|
|
6780
6779
|
name: "list_mocks",
|
|
6781
|
-
description: "List active
|
|
6780
|
+
description: "List active request-mocking sessions and hit counts.",
|
|
6782
6781
|
inputSchema: {
|
|
6783
6782
|
type: "object",
|
|
6784
6783
|
properties: {
|
|
6785
6784
|
lease: {
|
|
6786
6785
|
type: "string",
|
|
6787
|
-
description: "Lease token
|
|
6786
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6788
6787
|
},
|
|
6789
6788
|
target: {
|
|
6790
6789
|
type: "string",
|
|
@@ -6797,17 +6796,17 @@ var MANIFEST = [
|
|
|
6797
6796
|
},
|
|
6798
6797
|
{
|
|
6799
6798
|
name: "clear_mocks",
|
|
6800
|
-
description: "
|
|
6799
|
+
description: "Clear the selected or all request-mocking sessions.",
|
|
6801
6800
|
inputSchema: {
|
|
6802
6801
|
type: "object",
|
|
6803
6802
|
properties: {
|
|
6804
6803
|
lease: {
|
|
6805
6804
|
type: "string",
|
|
6806
|
-
description: "Lease token
|
|
6805
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6807
6806
|
},
|
|
6808
6807
|
target: {
|
|
6809
6808
|
type: "string",
|
|
6810
|
-
description: "
|
|
6809
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6811
6810
|
},
|
|
6812
6811
|
all: {
|
|
6813
6812
|
type: "boolean",
|
|
@@ -6820,29 +6819,29 @@ var MANIFEST = [
|
|
|
6820
6819
|
},
|
|
6821
6820
|
{
|
|
6822
6821
|
name: "claim_page",
|
|
6823
|
-
description: "
|
|
6822
|
+
description: "Claim an existing tab or open a fresh one; CLI use is refused.",
|
|
6824
6823
|
inputSchema: {
|
|
6825
6824
|
type: "object",
|
|
6826
6825
|
properties: {
|
|
6827
6826
|
target: {
|
|
6828
6827
|
type: "string",
|
|
6829
|
-
description: "
|
|
6828
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6830
6829
|
},
|
|
6831
6830
|
targetId: {
|
|
6832
6831
|
type: "string",
|
|
6833
|
-
description: "Exact target
|
|
6832
|
+
description: "Exact target ID."
|
|
6834
6833
|
},
|
|
6835
6834
|
url: {
|
|
6836
6835
|
type: "string",
|
|
6837
|
-
description: "
|
|
6836
|
+
description: "URL value."
|
|
6838
6837
|
},
|
|
6839
6838
|
label: {
|
|
6840
6839
|
type: "string",
|
|
6841
|
-
description: "Agent
|
|
6840
|
+
description: "Agent lease label."
|
|
6842
6841
|
},
|
|
6843
6842
|
ttlMs: {
|
|
6844
6843
|
type: "number",
|
|
6845
|
-
description: "
|
|
6844
|
+
description: "Lease TTL in milliseconds."
|
|
6846
6845
|
}
|
|
6847
6846
|
},
|
|
6848
6847
|
required: [],
|
|
@@ -6851,21 +6850,21 @@ var MANIFEST = [
|
|
|
6851
6850
|
},
|
|
6852
6851
|
{
|
|
6853
6852
|
name: "release_page",
|
|
6854
|
-
description: "
|
|
6853
|
+
description: "Release a page lease and optionally close its tab; provide lease or target.",
|
|
6855
6854
|
inputSchema: {
|
|
6856
6855
|
type: "object",
|
|
6857
6856
|
properties: {
|
|
6858
6857
|
lease: {
|
|
6859
6858
|
type: "string",
|
|
6860
|
-
description: "
|
|
6859
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
6861
6860
|
},
|
|
6862
6861
|
target: {
|
|
6863
6862
|
type: "string",
|
|
6864
|
-
description: "
|
|
6863
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
6865
6864
|
},
|
|
6866
6865
|
close: {
|
|
6867
6866
|
type: "boolean",
|
|
6868
|
-
description: "
|
|
6867
|
+
description: "Override close behavior."
|
|
6869
6868
|
}
|
|
6870
6869
|
},
|
|
6871
6870
|
required: [],
|
|
@@ -6874,7 +6873,7 @@ var MANIFEST = [
|
|
|
6874
6873
|
},
|
|
6875
6874
|
{
|
|
6876
6875
|
name: "list_leases",
|
|
6877
|
-
description: "
|
|
6876
|
+
description: "List active leases for diagnosis without exposing lease tokens.",
|
|
6878
6877
|
inputSchema: {
|
|
6879
6878
|
type: "object",
|
|
6880
6879
|
properties: {},
|
|
@@ -7081,6 +7080,252 @@ async function connectBidiSessionUrl(wsUrl, opts = {}) {
|
|
|
7081
7080
|
return conn;
|
|
7082
7081
|
}
|
|
7083
7082
|
|
|
7083
|
+
// src/bidi/session-lease.ts
|
|
7084
|
+
import { mkdir as mkdir12, readFile as readFile8, unlink as unlink5, writeFile as writeFile9 } from "node:fs/promises";
|
|
7085
|
+
import { join as join10 } from "node:path";
|
|
7086
|
+
var DEFAULT_SESSION_WAIT_MS = 1e4;
|
|
7087
|
+
var DEFAULT_POLL_MS = 250;
|
|
7088
|
+
function safeEndpoint(endpoint) {
|
|
7089
|
+
return endpoint.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
7090
|
+
}
|
|
7091
|
+
function sessionSlotFile(endpoint) {
|
|
7092
|
+
return join10(leaseDir(), `ff-session-${safeEndpoint(endpoint)}.json`);
|
|
7093
|
+
}
|
|
7094
|
+
function sessionWaitMs() {
|
|
7095
|
+
const raw = Number(process.env.CDP_FIREFOX_SESSION_WAIT_MS);
|
|
7096
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_SESSION_WAIT_MS;
|
|
7097
|
+
}
|
|
7098
|
+
|
|
7099
|
+
class SessionSlotBusyError extends Error {
|
|
7100
|
+
endpoint;
|
|
7101
|
+
holderPid;
|
|
7102
|
+
holderLabel;
|
|
7103
|
+
constructor(endpoint, holder) {
|
|
7104
|
+
const who = holder ? `'${holder.label}' (pid ${holder.pid})` : "another live process";
|
|
7105
|
+
super(`Firefox BiDi session slot for endpoint '${endpoint}' is held by ${who}. ` + `Firefox serves exactly ONE WebDriver-BiDi session per browser instance, and this slot is held ` + `by a LIVE process, so it cannot be taken. Wait for that process to release it and retry, or point ` + `this server at a different endpoint/browser.`);
|
|
7106
|
+
this.name = "SessionSlotBusyError";
|
|
7107
|
+
this.endpoint = endpoint;
|
|
7108
|
+
if (holder) {
|
|
7109
|
+
this.holderPid = holder.pid;
|
|
7110
|
+
this.holderLabel = holder.label;
|
|
7111
|
+
}
|
|
7112
|
+
}
|
|
7113
|
+
}
|
|
7114
|
+
async function readSessionSlot(endpoint) {
|
|
7115
|
+
let raw;
|
|
7116
|
+
try {
|
|
7117
|
+
raw = await readFile8(sessionSlotFile(endpoint), "utf8");
|
|
7118
|
+
} catch (err) {
|
|
7119
|
+
if (err.code === "ENOENT")
|
|
7120
|
+
return;
|
|
7121
|
+
throw err;
|
|
7122
|
+
}
|
|
7123
|
+
try {
|
|
7124
|
+
const rec = JSON.parse(raw);
|
|
7125
|
+
if (typeof rec?.pid === "number" && typeof rec?.endpoint === "string" && typeof rec?.label === "string") {
|
|
7126
|
+
return rec;
|
|
7127
|
+
}
|
|
7128
|
+
} catch {}
|
|
7129
|
+
return;
|
|
7130
|
+
}
|
|
7131
|
+
async function acquireSessionSlot(endpoint, opts) {
|
|
7132
|
+
const waitMs = opts.waitMs ?? sessionWaitMs();
|
|
7133
|
+
const pollMs = opts.pollMs !== undefined && opts.pollMs > 0 ? opts.pollMs : DEFAULT_POLL_MS;
|
|
7134
|
+
const createdAt = opts.now ?? Date.now();
|
|
7135
|
+
const file = sessionSlotFile(endpoint);
|
|
7136
|
+
const record2 = {
|
|
7137
|
+
endpoint,
|
|
7138
|
+
pid: process.pid,
|
|
7139
|
+
label: opts.label,
|
|
7140
|
+
createdAt
|
|
7141
|
+
};
|
|
7142
|
+
if (opts.marionettePort !== undefined)
|
|
7143
|
+
record2.marionettePort = opts.marionettePort;
|
|
7144
|
+
const handle = { endpoint, pid: process.pid, createdAt };
|
|
7145
|
+
const payload = JSON.stringify(record2);
|
|
7146
|
+
await mkdir12(leaseDir(), { recursive: true });
|
|
7147
|
+
const deadline = Date.now() + waitMs;
|
|
7148
|
+
const maxAttempts = Math.max(100, Math.ceil(waitMs / pollMs) + 100);
|
|
7149
|
+
let attempts = 0;
|
|
7150
|
+
let lastLiveHolder;
|
|
7151
|
+
while (true) {
|
|
7152
|
+
if (attempts >= maxAttempts)
|
|
7153
|
+
throw new SessionSlotBusyError(endpoint, lastLiveHolder);
|
|
7154
|
+
attempts++;
|
|
7155
|
+
try {
|
|
7156
|
+
await writeFile9(file, payload, { flag: "wx" });
|
|
7157
|
+
return { handle };
|
|
7158
|
+
} catch (err) {
|
|
7159
|
+
if (err.code !== "EEXIST")
|
|
7160
|
+
throw err;
|
|
7161
|
+
}
|
|
7162
|
+
const holder = await readSessionSlot(endpoint);
|
|
7163
|
+
if (!holder)
|
|
7164
|
+
continue;
|
|
7165
|
+
if (!isPidAlive(holder.pid)) {
|
|
7166
|
+
await unlink5(file).catch(() => {
|
|
7167
|
+
return;
|
|
7168
|
+
});
|
|
7169
|
+
try {
|
|
7170
|
+
await writeFile9(file, payload, { flag: "wx" });
|
|
7171
|
+
return { handle, staleHolder: holder };
|
|
7172
|
+
} catch (err) {
|
|
7173
|
+
if (err.code !== "EEXIST")
|
|
7174
|
+
throw err;
|
|
7175
|
+
continue;
|
|
7176
|
+
}
|
|
7177
|
+
}
|
|
7178
|
+
lastLiveHolder = holder;
|
|
7179
|
+
const remaining = deadline - Date.now();
|
|
7180
|
+
if (remaining <= 0)
|
|
7181
|
+
throw new SessionSlotBusyError(endpoint, holder);
|
|
7182
|
+
await sleep2(Math.min(pollMs, remaining));
|
|
7183
|
+
}
|
|
7184
|
+
}
|
|
7185
|
+
async function releaseSessionSlot(handle) {
|
|
7186
|
+
const current = await readSessionSlot(handle.endpoint);
|
|
7187
|
+
if (!current)
|
|
7188
|
+
return { released: false };
|
|
7189
|
+
if (current.pid !== process.pid || current.createdAt !== handle.createdAt)
|
|
7190
|
+
return { released: false };
|
|
7191
|
+
await unlink5(sessionSlotFile(handle.endpoint)).catch(() => {
|
|
7192
|
+
return;
|
|
7193
|
+
});
|
|
7194
|
+
return { released: true };
|
|
7195
|
+
}
|
|
7196
|
+
function sleep2(ms) {
|
|
7197
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7198
|
+
}
|
|
7199
|
+
|
|
7200
|
+
// src/bidi/marionette.ts
|
|
7201
|
+
import { Socket } from "node:net";
|
|
7202
|
+
var DEFAULT_MARIONETTE_PORT = 2828;
|
|
7203
|
+
var DEFAULT_TIMEOUT_MS3 = 4000;
|
|
7204
|
+
var HOST = "127.0.0.1";
|
|
7205
|
+
var COLON = 58;
|
|
7206
|
+
var DELETE_SESSION_FRAME = encodeFrame([0, 1, "WebDriver:DeleteSession", {}]);
|
|
7207
|
+
function defaultMarionettePort() {
|
|
7208
|
+
const raw = Number(process.env.CDP_FIREFOX_MARIONETTE_PORT);
|
|
7209
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_MARIONETTE_PORT;
|
|
7210
|
+
}
|
|
7211
|
+
function encodeFrame(json) {
|
|
7212
|
+
const body = Buffer.from(JSON.stringify(json), "utf8");
|
|
7213
|
+
const prefix = Buffer.from(`${body.length}:`, "ascii");
|
|
7214
|
+
return Buffer.concat([prefix, body]);
|
|
7215
|
+
}
|
|
7216
|
+
|
|
7217
|
+
class MarionetteProtocolError extends Error {
|
|
7218
|
+
constructor(message) {
|
|
7219
|
+
super(message);
|
|
7220
|
+
this.name = "MarionetteProtocolError";
|
|
7221
|
+
}
|
|
7222
|
+
}
|
|
7223
|
+
|
|
7224
|
+
class FrameDecoder {
|
|
7225
|
+
buf = Buffer.alloc(0);
|
|
7226
|
+
push(chunk) {
|
|
7227
|
+
this.buf = this.buf.length === 0 ? chunk : Buffer.concat([this.buf, chunk]);
|
|
7228
|
+
}
|
|
7229
|
+
next() {
|
|
7230
|
+
const colon = this.buf.indexOf(COLON);
|
|
7231
|
+
if (colon === -1) {
|
|
7232
|
+
this.assertDigitsPrefix(this.buf.length);
|
|
7233
|
+
return;
|
|
7234
|
+
}
|
|
7235
|
+
if (colon === 0)
|
|
7236
|
+
throw new MarionetteProtocolError("empty frame length prefix");
|
|
7237
|
+
this.assertDigitsPrefix(colon);
|
|
7238
|
+
const len = Number.parseInt(this.buf.toString("ascii", 0, colon), 10);
|
|
7239
|
+
const start = colon + 1;
|
|
7240
|
+
const end = start + len;
|
|
7241
|
+
if (this.buf.length < end)
|
|
7242
|
+
return;
|
|
7243
|
+
const payload = this.buf.toString("utf8", start, end);
|
|
7244
|
+
this.buf = this.buf.subarray(end);
|
|
7245
|
+
try {
|
|
7246
|
+
return JSON.parse(payload);
|
|
7247
|
+
} catch {
|
|
7248
|
+
throw new MarionetteProtocolError(`frame body was not valid JSON (${len} bytes): ${payload.slice(0, 80)}`);
|
|
7249
|
+
}
|
|
7250
|
+
}
|
|
7251
|
+
assertDigitsPrefix(upTo) {
|
|
7252
|
+
for (let i = 0;i < upTo; i++) {
|
|
7253
|
+
const b = this.buf[i];
|
|
7254
|
+
if (b < 48 || b > 57) {
|
|
7255
|
+
throw new MarionetteProtocolError(`non-digit byte 0x${b.toString(16)} in frame length prefix`);
|
|
7256
|
+
}
|
|
7257
|
+
}
|
|
7258
|
+
}
|
|
7259
|
+
}
|
|
7260
|
+
function isSlotFreedReply(frame) {
|
|
7261
|
+
if (!Array.isArray(frame))
|
|
7262
|
+
return false;
|
|
7263
|
+
const err = frame[2];
|
|
7264
|
+
if (err === null)
|
|
7265
|
+
return true;
|
|
7266
|
+
if (typeof err === "object" && err !== null && err.error === "invalid session id") {
|
|
7267
|
+
return true;
|
|
7268
|
+
}
|
|
7269
|
+
return false;
|
|
7270
|
+
}
|
|
7271
|
+
function forceClearOrphanSession(marionettePort, opts = {}) {
|
|
7272
|
+
const timeoutMs = opts.timeoutMs !== undefined && Number.isFinite(opts.timeoutMs) && opts.timeoutMs > 0 ? opts.timeoutMs : DEFAULT_TIMEOUT_MS3;
|
|
7273
|
+
return new Promise((resolve) => {
|
|
7274
|
+
if (!Number.isFinite(marionettePort) || marionettePort <= 0 || marionettePort > 65535) {
|
|
7275
|
+
resolve(false);
|
|
7276
|
+
return;
|
|
7277
|
+
}
|
|
7278
|
+
const sock = new Socket;
|
|
7279
|
+
const decoder = new FrameDecoder;
|
|
7280
|
+
let settled = false;
|
|
7281
|
+
let handshakeSeen = false;
|
|
7282
|
+
let commandSent = false;
|
|
7283
|
+
const settle = (value) => {
|
|
7284
|
+
if (settled)
|
|
7285
|
+
return;
|
|
7286
|
+
settled = true;
|
|
7287
|
+
clearTimeout(timer);
|
|
7288
|
+
sock.removeAllListeners();
|
|
7289
|
+
sock.destroy();
|
|
7290
|
+
resolve(value);
|
|
7291
|
+
};
|
|
7292
|
+
const timer = setTimeout(() => settle(false), timeoutMs);
|
|
7293
|
+
if (typeof timer.unref === "function")
|
|
7294
|
+
timer.unref();
|
|
7295
|
+
sock.on("error", () => settle(false));
|
|
7296
|
+
sock.on("close", () => settle(false));
|
|
7297
|
+
sock.on("data", (chunk) => {
|
|
7298
|
+
if (settled)
|
|
7299
|
+
return;
|
|
7300
|
+
try {
|
|
7301
|
+
decoder.push(chunk);
|
|
7302
|
+
for (;; ) {
|
|
7303
|
+
const frame = decoder.next();
|
|
7304
|
+
if (frame === undefined)
|
|
7305
|
+
break;
|
|
7306
|
+
if (!handshakeSeen) {
|
|
7307
|
+
handshakeSeen = true;
|
|
7308
|
+
continue;
|
|
7309
|
+
}
|
|
7310
|
+
settle(isSlotFreedReply(frame));
|
|
7311
|
+
return;
|
|
7312
|
+
}
|
|
7313
|
+
if (handshakeSeen && !commandSent) {
|
|
7314
|
+
commandSent = true;
|
|
7315
|
+
sock.write(DELETE_SESSION_FRAME);
|
|
7316
|
+
}
|
|
7317
|
+
} catch {
|
|
7318
|
+
settle(false);
|
|
7319
|
+
}
|
|
7320
|
+
});
|
|
7321
|
+
try {
|
|
7322
|
+
sock.connect(marionettePort, HOST);
|
|
7323
|
+
} catch {
|
|
7324
|
+
settle(false);
|
|
7325
|
+
}
|
|
7326
|
+
});
|
|
7327
|
+
}
|
|
7328
|
+
|
|
7084
7329
|
// src/bidi/snapshot.ts
|
|
7085
7330
|
var STAMP_ATTR = "data-cdp-uid";
|
|
7086
7331
|
async function takeStampedSnapshot(evaluate) {
|
|
@@ -7459,6 +7704,9 @@ function mapBidiError(e) {
|
|
|
7459
7704
|
return driverError2("timeout", e.message);
|
|
7460
7705
|
if (!code && /(disposed|not open|connection closed)/i.test(e.message))
|
|
7461
7706
|
return driverError2("disconnected", e.message);
|
|
7707
|
+
if (/NS_ERROR_FILE_ACCESS_DENIED/i.test(e.message)) {
|
|
7708
|
+
return driverError2("page-error", `${e.message} — the browser process was not allowed to open this file:// path. For a snap- or AppArmor-confined Firefox (Ubuntu default) that is kernel-level and no preference fixes it: serve the directory over a local http server (e.g. python3 -m http.server) and navigate to the http://127.0.0.1:<port>/ URL instead. If this Firefox was launched by cdp-toolkit and still fails, please report it at https://github.com/sblattj/cdp-toolkit/issues.`);
|
|
7709
|
+
}
|
|
7462
7710
|
return driverError2("page-error", e.message);
|
|
7463
7711
|
}
|
|
7464
7712
|
return driverError2("page-error", e instanceof Error ? e.message : String(e));
|
|
@@ -7657,6 +7905,22 @@ var BIDI_CAPABILITIES = new Set([
|
|
|
7657
7905
|
"locate.xpath"
|
|
7658
7906
|
]);
|
|
7659
7907
|
var connections = new Map;
|
|
7908
|
+
var slotHandles = new Map;
|
|
7909
|
+
var connecting = new Map;
|
|
7910
|
+
async function releaseSlotOnDialFailure(endpoint, owned) {
|
|
7911
|
+
if (owned)
|
|
7912
|
+
return;
|
|
7913
|
+
const h = slotHandles.get(endpoint);
|
|
7914
|
+
if (h) {
|
|
7915
|
+
await releaseSessionSlot(h).catch(() => {
|
|
7916
|
+
return;
|
|
7917
|
+
});
|
|
7918
|
+
slotHandles.delete(endpoint);
|
|
7919
|
+
}
|
|
7920
|
+
}
|
|
7921
|
+
function orphanNotClearedError(endpoint) {
|
|
7922
|
+
return driverError2("disconnected", `Firefox holds an orphaned WebDriver BiDi session on ${endpoint} that could not be auto-cleared. ` + `Marionette recovery needs Firefox launched with --marionette (default port 2828, or set ` + `CDP_FIREFOX_MARIONETTE_PORT); otherwise restart Firefox to free the slot. (A client killed without ` + `session.end can leave a session Firefox does not reap.)`);
|
|
7923
|
+
}
|
|
7660
7924
|
async function getConnection(endpoint, timeoutMs) {
|
|
7661
7925
|
const existing = connections.get(endpoint);
|
|
7662
7926
|
if (existing && existing.isOpen) {
|
|
@@ -7665,17 +7929,68 @@ async function getConnection(endpoint, timeoutMs) {
|
|
|
7665
7929
|
}
|
|
7666
7930
|
if (existing)
|
|
7667
7931
|
connections.delete(endpoint);
|
|
7668
|
-
const
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
|
|
7932
|
+
const inflight = connecting.get(endpoint);
|
|
7933
|
+
if (inflight) {
|
|
7934
|
+
const conn = await inflight;
|
|
7935
|
+
conn.retain();
|
|
7936
|
+
return conn;
|
|
7937
|
+
}
|
|
7938
|
+
const create = (async () => {
|
|
7939
|
+
const mport = defaultMarionettePort();
|
|
7940
|
+
const owned = slotHandles.has(endpoint);
|
|
7941
|
+
if (!owned) {
|
|
7942
|
+
let acq;
|
|
7943
|
+
try {
|
|
7944
|
+
acq = await acquireSessionSlot(endpoint, { label: defaultLabel(), marionettePort: mport });
|
|
7945
|
+
} catch (e) {
|
|
7946
|
+
if (e instanceof SessionSlotBusyError) {
|
|
7947
|
+
const who = e.holderLabel ? `'${e.holderLabel}' (pid ${e.holderPid})` : "another live process";
|
|
7948
|
+
throw driverError2("disconnected", `Firefox's single WebDriver BiDi session on ${endpoint} is held by a LIVE process ${who}. ` + `Firefox serves exactly ONE BiDi session per browser instance, so this server cannot take it ` + `while that process is running. Wait for it to release the session and retry, or point this ` + `server at a different endpoint/browser.`);
|
|
7949
|
+
}
|
|
7950
|
+
throw e;
|
|
7951
|
+
}
|
|
7952
|
+
slotHandles.set(endpoint, acq.handle);
|
|
7953
|
+
if (acq.staleHolder) {
|
|
7954
|
+
await forceClearOrphanSession(acq.staleHolder.marionettePort ?? mport);
|
|
7955
|
+
}
|
|
7674
7956
|
}
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7957
|
+
const dialOpts = {
|
|
7958
|
+
...timeoutMs !== undefined ? { timeoutMs } : {},
|
|
7959
|
+
capabilities: { alwaysMatch: { unhandledPromptBehavior: { default: "ignore" } } }
|
|
7960
|
+
};
|
|
7961
|
+
let conn;
|
|
7962
|
+
try {
|
|
7963
|
+
conn = await connectBidiSessionUrl(endpoint, dialOpts);
|
|
7964
|
+
} catch (e) {
|
|
7965
|
+
if (e instanceof BidiError && /maximum number of active sessions/i.test(e.message)) {
|
|
7966
|
+
const cleared = await forceClearOrphanSession(mport);
|
|
7967
|
+
if (!cleared) {
|
|
7968
|
+
await releaseSlotOnDialFailure(endpoint, owned);
|
|
7969
|
+
throw orphanNotClearedError(endpoint);
|
|
7970
|
+
}
|
|
7971
|
+
try {
|
|
7972
|
+
conn = await connectBidiSessionUrl(endpoint, dialOpts);
|
|
7973
|
+
} catch (e2) {
|
|
7974
|
+
await releaseSlotOnDialFailure(endpoint, owned);
|
|
7975
|
+
if (e2 instanceof BidiError && /maximum number of active sessions/i.test(e2.message)) {
|
|
7976
|
+
throw orphanNotClearedError(endpoint);
|
|
7977
|
+
}
|
|
7978
|
+
throw e2;
|
|
7979
|
+
}
|
|
7980
|
+
} else {
|
|
7981
|
+
await releaseSlotOnDialFailure(endpoint, owned);
|
|
7982
|
+
throw e;
|
|
7983
|
+
}
|
|
7984
|
+
}
|
|
7985
|
+
connections.set(endpoint, conn);
|
|
7986
|
+
return conn;
|
|
7987
|
+
})();
|
|
7988
|
+
connecting.set(endpoint, create);
|
|
7989
|
+
try {
|
|
7990
|
+
return await create;
|
|
7991
|
+
} finally {
|
|
7992
|
+
connecting.delete(endpoint);
|
|
7993
|
+
}
|
|
7679
7994
|
}
|
|
7680
7995
|
var bidiBeaconScripts = new Map;
|
|
7681
7996
|
async function safeTitle(conn, contextId) {
|
|
@@ -7788,7 +8103,10 @@ class BidiPageDriver {
|
|
|
7788
8103
|
const sendOpts = opts.timeoutMs !== undefined ? { timeoutMs: opts.timeoutMs } : {};
|
|
7789
8104
|
try {
|
|
7790
8105
|
if (reload) {
|
|
7791
|
-
|
|
8106
|
+
if (opts.ignoreCache === true) {
|
|
8107
|
+
throw driverError2("unsupported", "navigate: ignoreCache:true (hard reload) is not supported on the Firefox WebDriver-BiDi backend — Firefox rejects the ignoreCache argument outright. A plain reload (reload:true, no ignoreCache) works.");
|
|
8108
|
+
}
|
|
8109
|
+
const r2 = await this.conn.send("browsingContext.reload", { context: this.contextId, wait }, sendOpts);
|
|
7792
8110
|
return { url: r2.url, contextId: this.contextId, reloaded: true, waitedFor: waitUntil };
|
|
7793
8111
|
}
|
|
7794
8112
|
if (history) {
|
|
@@ -8441,14 +8759,27 @@ class BidiBrowserDriver {
|
|
|
8441
8759
|
if (key.startsWith(`${this.endpoint}:`))
|
|
8442
8760
|
bidiBeaconScripts.delete(key);
|
|
8443
8761
|
}
|
|
8762
|
+
connecting.delete(this.endpoint);
|
|
8444
8763
|
const conn = connections.get(this.endpoint);
|
|
8445
|
-
if (!conn)
|
|
8764
|
+
if (!conn) {
|
|
8765
|
+
await this.releaseSessionSlotIfHeld();
|
|
8446
8766
|
return;
|
|
8767
|
+
}
|
|
8447
8768
|
connections.delete(this.endpoint);
|
|
8448
8769
|
await conn.send("session.end", {}).catch(() => {
|
|
8449
8770
|
return;
|
|
8450
8771
|
});
|
|
8451
8772
|
conn.dispose();
|
|
8773
|
+
await this.releaseSessionSlotIfHeld();
|
|
8774
|
+
}
|
|
8775
|
+
async releaseSessionSlotIfHeld() {
|
|
8776
|
+
const h = slotHandles.get(this.endpoint);
|
|
8777
|
+
if (!h)
|
|
8778
|
+
return;
|
|
8779
|
+
await releaseSessionSlot(h).catch(() => {
|
|
8780
|
+
return;
|
|
8781
|
+
});
|
|
8782
|
+
slotHandles.delete(this.endpoint);
|
|
8452
8783
|
}
|
|
8453
8784
|
}
|
|
8454
8785
|
function createFirefoxDriver(port, opts) {
|
|
@@ -8460,10 +8791,10 @@ function createFirefoxDriverForEndpoint(wsUrl, opts) {
|
|
|
8460
8791
|
|
|
8461
8792
|
// src/bidi/launch.ts
|
|
8462
8793
|
import { spawn as spawn3 } from "node:child_process";
|
|
8463
|
-
import { existsSync, mkdtempSync, rmSync } from "node:fs";
|
|
8794
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
8464
8795
|
import { createConnection, createServer } from "node:net";
|
|
8465
8796
|
import { tmpdir } from "node:os";
|
|
8466
|
-
import { join as
|
|
8797
|
+
import { join as join11 } from "node:path";
|
|
8467
8798
|
function resolveBinary() {
|
|
8468
8799
|
const candidates = [
|
|
8469
8800
|
process.env.FIREFOX_BIN,
|
|
@@ -8537,11 +8868,37 @@ function waitForExit(proc, deadlineMs) {
|
|
|
8537
8868
|
});
|
|
8538
8869
|
});
|
|
8539
8870
|
}
|
|
8871
|
+
var LAUNCH_USER_JS_PREFS = {
|
|
8872
|
+
"remote.prefs.recommended": true,
|
|
8873
|
+
"security.fileuri.strict_origin_policy": false,
|
|
8874
|
+
"dom.file.createInChild": true
|
|
8875
|
+
};
|
|
8876
|
+
function writeLaunchUserJs(profilePath) {
|
|
8877
|
+
const target = join11(profilePath, "user.js");
|
|
8878
|
+
const existing = existsSync(target) ? readFileSync(target, "utf8") : "";
|
|
8879
|
+
const present = new Set;
|
|
8880
|
+
for (const line of existing.split(`
|
|
8881
|
+
`)) {
|
|
8882
|
+
const m = /^user_pref\("([^"]+)"\s*,/.exec(line.trim());
|
|
8883
|
+
if (m)
|
|
8884
|
+
present.add(m[1]);
|
|
8885
|
+
}
|
|
8886
|
+
const additions = Object.entries(LAUNCH_USER_JS_PREFS).filter(([k]) => !present.has(k)).map(([k, v]) => `user_pref("${k}", ${JSON.stringify(v)});`);
|
|
8887
|
+
const content = (existing.length > 0 ? existing.replace(/\n*$/, `
|
|
8888
|
+
`) : "") + additions.join(`
|
|
8889
|
+
`) + (additions.length > 0 ? `
|
|
8890
|
+
` : "");
|
|
8891
|
+
if (content !== existing)
|
|
8892
|
+
writeFileSync(target, content, "utf-8");
|
|
8893
|
+
return content;
|
|
8894
|
+
}
|
|
8540
8895
|
async function launchFirefox(opts = {}) {
|
|
8541
8896
|
const binary = resolveBinary();
|
|
8542
8897
|
const port = await pickPort(opts.port);
|
|
8543
8898
|
const isThrowaway = opts.profilePath === undefined;
|
|
8544
|
-
const profilePath = opts.profilePath ?? mkdtempSync(
|
|
8899
|
+
const profilePath = opts.profilePath ?? mkdtempSync(join11(tmpdir(), "cdp-toolkit-ff-profile-"));
|
|
8900
|
+
if (isThrowaway)
|
|
8901
|
+
writeLaunchUserJs(profilePath);
|
|
8545
8902
|
const args = ["--profile", profilePath, "--remote-debugging-port", String(port), "--no-remote"];
|
|
8546
8903
|
if (opts.headless)
|
|
8547
8904
|
args.push("--headless");
|
|
@@ -8891,8 +9248,545 @@ var FIREFOX_TOOLS = {
|
|
|
8891
9248
|
...LEASE_TOOLS
|
|
8892
9249
|
};
|
|
8893
9250
|
|
|
9251
|
+
// src/toolGroups.ts
|
|
9252
|
+
var TOOL_GROUPS = [
|
|
9253
|
+
"core",
|
|
9254
|
+
"input",
|
|
9255
|
+
"cookies",
|
|
9256
|
+
"network",
|
|
9257
|
+
"console",
|
|
9258
|
+
"mocking",
|
|
9259
|
+
"emulation",
|
|
9260
|
+
"performance",
|
|
9261
|
+
"recording",
|
|
9262
|
+
"leases",
|
|
9263
|
+
"permissions",
|
|
9264
|
+
"dialogs",
|
|
9265
|
+
"downloads"
|
|
9266
|
+
];
|
|
9267
|
+
var GROUP_TOOLS = {
|
|
9268
|
+
core: [
|
|
9269
|
+
"list_pages",
|
|
9270
|
+
"new_page",
|
|
9271
|
+
"close_page",
|
|
9272
|
+
"select_page",
|
|
9273
|
+
"navigate_page",
|
|
9274
|
+
"wait_for",
|
|
9275
|
+
"take_snapshot",
|
|
9276
|
+
"click",
|
|
9277
|
+
"fill",
|
|
9278
|
+
"type_text",
|
|
9279
|
+
"evaluate_script",
|
|
9280
|
+
"take_screenshot"
|
|
9281
|
+
],
|
|
9282
|
+
input: [
|
|
9283
|
+
"hover",
|
|
9284
|
+
"drag",
|
|
9285
|
+
"scroll",
|
|
9286
|
+
"dispatch_mouse",
|
|
9287
|
+
"press_key",
|
|
9288
|
+
"fill_form",
|
|
9289
|
+
"upload_file"
|
|
9290
|
+
],
|
|
9291
|
+
cookies: ["list_cookies", "set_cookie", "delete_cookies"],
|
|
9292
|
+
network: ["list_network_requests", "get_network_request"],
|
|
9293
|
+
console: ["list_console_messages", "get_console_message"],
|
|
9294
|
+
mocking: ["mock_request", "list_mocks", "clear_mocks"],
|
|
9295
|
+
emulation: ["emulate", "resize_page"],
|
|
9296
|
+
performance: [
|
|
9297
|
+
"performance_start_trace",
|
|
9298
|
+
"performance_stop_trace",
|
|
9299
|
+
"performance_analyze_insight",
|
|
9300
|
+
"performance_trace",
|
|
9301
|
+
"take_heapsnapshot",
|
|
9302
|
+
"lighthouse_audit"
|
|
9303
|
+
],
|
|
9304
|
+
recording: ["start_screen_recording", "stop_screen_recording"],
|
|
9305
|
+
leases: ["claim_page", "release_page", "list_leases"],
|
|
9306
|
+
permissions: ["grant_permissions"],
|
|
9307
|
+
dialogs: ["handle_dialog"],
|
|
9308
|
+
downloads: ["wait_for_download"]
|
|
9309
|
+
};
|
|
9310
|
+
var TOOL_GROUP = {};
|
|
9311
|
+
for (const group of TOOL_GROUPS) {
|
|
9312
|
+
for (const tool of GROUP_TOOLS[group]) {
|
|
9313
|
+
TOOL_GROUP[tool] = group;
|
|
9314
|
+
}
|
|
9315
|
+
}
|
|
9316
|
+
var PROFILES = {
|
|
9317
|
+
core: ["core"],
|
|
9318
|
+
full: [...TOOL_GROUPS]
|
|
9319
|
+
};
|
|
9320
|
+
|
|
9321
|
+
// src/toolDocs.ts
|
|
9322
|
+
var TOOL_DOCS = {
|
|
9323
|
+
list_pages: {
|
|
9324
|
+
description: "Enumerate browser page targets (GET /json/list); page-type tabs only unless all=true. Each entry carries its targetId plus an origin field: 'agent' means this toolkit created it (also carries the creating label/createdAt, and stays 'agent' after the lease is released or the creator dies, making stray agent tabs findable), 'unknown' means no creation record - it never says 'human', the honest word for any tab it did not create; a record that exists but won't read adds originUnreadable. An entry under an active, readable lease also carries a 'lease' object {label,pid,idleMs,expiresAt,stale}, with idleMs and expiresAt computed fresh every call (never off disk), independent of probe. Under CDP_REQUIRE_LEASE this call also reaps abandoned agent tabs into an additive reaped array - but a lease reads reclaimable the moment its TTL elapses, while the tab is CLOSED only after a further grace (CDP_REAP_GRACE_MS, default 2700000ms/45min, so 60min total after last use); a dead-pid lease is reaped at once, a tab with no lease never. With probe, each page-type entry also gets 'responsive' (and humanActiveMs where human input is seen); both are absent, never false/null, without probe.",
|
|
9325
|
+
params: {
|
|
9326
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9327
|
+
all: "Include non-page targets (service/shared workers, background pages); default false lists page-type tabs only.",
|
|
9328
|
+
probe: "Ping each page-type renderer before returning, one bounded 500ms check per target and never more, so a wedged tab can't stall the listing. Adds 'responsive' (false on timeout/exception/unreachable, never an error for the whole call) and, where the same round trip finds human input, humanActiveMs. Default false. On a backend that cannot answer the ping, responsive is absent too (not false)."
|
|
9329
|
+
}
|
|
9330
|
+
},
|
|
9331
|
+
new_page: {
|
|
9332
|
+
description: "Open a new browser tab via Target.createTarget and return {targetId,url}. Defaults to about:blank; navigation is not awaited here (use navigate_page to load and wait).",
|
|
9333
|
+
params: {
|
|
9334
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9335
|
+
url: "URL to open in the new tab; defaults to about:blank.",
|
|
9336
|
+
claim: "Claim the new tab atomically and return a lease token alongside {targetId,url}. Under CDP_REQUIRE_LEASE the tab is claimed and a lease returned even without claim:true; claim:true makes it an EXPLICIT lease that demands its token on every later call, even from this process. Default false.",
|
|
9337
|
+
label: "Agent label recorded on the lease when the tab is claimed; surfaced in conflict errors and list_leases. Defaults to pid-<pid>.",
|
|
9338
|
+
ttlMs: "How long a claimed lease survives without use before it is reclaimable. Defaults to CDP_LEASE_TTL_MS, else 900000 (15min); every checked call refreshes it. Ignored when not claiming."
|
|
9339
|
+
}
|
|
9340
|
+
},
|
|
9341
|
+
close_page: {
|
|
9342
|
+
description: "Close a page target via Target.closeTarget. Requires an explicit, resolvable target; errors rather than guessing when the selector matches nothing.",
|
|
9343
|
+
params: {
|
|
9344
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9345
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions."
|
|
9346
|
+
}
|
|
9347
|
+
},
|
|
9348
|
+
select_page: {
|
|
9349
|
+
description: "Activate/focus a page target via Target.activateTarget and persist its bare targetId to the selected-state file (CDP_STATE_DIR/selected). Requires an explicit, resolvable target.",
|
|
9350
|
+
params: {
|
|
9351
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9352
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions."
|
|
9353
|
+
}
|
|
9354
|
+
},
|
|
9355
|
+
navigate_page: {
|
|
9356
|
+
description: "Navigate a target page to a URL (Page.navigate), reload it (reload:true), OR go back/forward in its session history (history:'back'|'forward'), then wait for the load milestone with a bounded timeout so a wedged renderer can't hang. Exactly one of url / reload / history per call. Returns {url,frameId,waitedFor} (plus reloaded:true on a reload, traversed:'back'|'forward' on a history move); waitUntil supports 'load'|'domcontentloaded' only (no 'networkidle'), and there is no auto-snapshot of the new page. Pass reload:true with ignoreCache:true for a hard reload that refetches every subresource (e.g. to pick up a freshly-deployed, non-content-hashed bundle the HTTP cache would serve stale).",
|
|
9357
|
+
params: {
|
|
9358
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9359
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9360
|
+
url: "Destination URL to navigate to. Required unless reload:true.",
|
|
9361
|
+
reload: "Reload the current page (Page.reload) instead of navigating to url. Default false.",
|
|
9362
|
+
history: "Traverse this tab's session history instead of loading a url: 'back' and 'forward' are the browser's Back and Forward buttons. Mutually exclusive with 'url' and 'reload' — passing two of the three is refused by name, not resolved by precedence. Works on BOTH backends and waits for the same load milestone as an ordinary navigation. Going back from the first entry, or forward from the last, is an ERROR naming the direction — never a silent no-op. The result carries traversed:'back'|'forward' alongside the resulting url.",
|
|
9363
|
+
ignoreCache: "On reload, bypass the HTTP cache (hard reload) so subresources are refetched. Ignored unless reload:true. Chrome only: Firefox's WebDriver-BiDi rejects the ignoreCache argument outright, so reload+ignoreCache on Firefox throws a clear unsupported error instead (a plain reload works). Default false.",
|
|
9364
|
+
waitUntil: "Which load milestone to wait for. Defaults to 'load'. No 'networkidle' support.",
|
|
9365
|
+
timeoutMs: "Override the navigation timeout in milliseconds."
|
|
9366
|
+
}
|
|
9367
|
+
},
|
|
9368
|
+
wait_for: {
|
|
9369
|
+
description: "Poll the target until the substring appears in document.body.innerText (Runtime.evaluate on a fixed interval), or throw on timeout. Text-substring only -- no aria/role/selector or event variants; throws rather than returning {found:false}.",
|
|
9370
|
+
params: {
|
|
9371
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9372
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9373
|
+
text: "Substring to wait for in document.body.innerText. Required.",
|
|
9374
|
+
timeoutMs: "Total time budget in ms. Default 15000.",
|
|
9375
|
+
pollMs: "Poll interval in ms. Default 250."
|
|
9376
|
+
}
|
|
9377
|
+
},
|
|
9378
|
+
evaluate_script: {
|
|
9379
|
+
description: "Run arbitrary JavaScript in the target's main-world context over raw CDP and return the evaluated value (returnByValue). With no 'args', 'expression' is a raw expression; with 'args' it must be a function literal (arrow or classic) invoked on globalThis with args passed positionally. A thrown exception surfaces as an error; non-serializable returns (DOM nodes, functions) come back as their CDP description string. savePath writes the value to a JSON file instead -- the response then carries only {path,bytes,type,target} and the value never appears in it, the way to read a credential (a JWT/session token from localStorage) without putting the secret in the transcript. This is the one tool that EVALUATES inside an MV3 extension's background SERVICE WORKER rather than OBSERVING it (Chrome, Capability 'worker.targets'): a worker: target reads chrome.storage.local, chrome.runtime and the worker's own globals directly, with an idle-evicted worker started first (see 'wake').",
|
|
9380
|
+
params: {
|
|
9381
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9382
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', '<targetId>'; plus 'worker:<substring>' to reach a service/shared worker (e.g. an MV3 extension background worker). The worker: arm is CHROME-ONLY (Capability 'worker.targets'). Grammar: see server instructions.",
|
|
9383
|
+
wake: "Worker targets only, when starting a capture. Default true: an idle-evicted MV3 service worker exists in no target listing, so it is started first (ServiceWorker.startWorker) and re-confirmed; false fails fast. Rejected on a page target, a bare target id, or a read-only call. See server instructions.",
|
|
9384
|
+
expression: "JavaScript to run. Evaluated as an expression when 'args' is omitted; must be a function literal (arrow or classic) whose parameters receive 'args' when provided. REQUIRED -- the code always goes in this key, never in 'function', 'code', 'js', 'script', 'fn' or 'body'; a call using one of those is rejected with an error naming the wrong key.",
|
|
9385
|
+
awaitPromise: "Await the result if it is a Promise. Default true.",
|
|
9386
|
+
args: "Positional JSON-serializable arguments passed to the expression (treated as a function). No live element/page handle is bound.",
|
|
9387
|
+
savePath: "Write the evaluated value to this file as JSON and KEEP IT OUT OF THE RESPONSE: the result is {path,bytes,type,target} only, with no copy, preview or truncation of the value -- read credentials without putting them in a transcript. An absolute path (starting with /) is used as-is; a relative path resolves under the artifact dir (/tmp/cdp-toolkit); missing parents are created. Omit to get the value back inline."
|
|
9388
|
+
}
|
|
9389
|
+
},
|
|
9390
|
+
list_cookies: {
|
|
9391
|
+
description: "Read the target page's cookie store INCLUDING httpOnly cookies, which document.cookie (and therefore evaluate_script) cannot see. Page-scoped, not browser-wide: returns cookies of the resolved tab, so point at a page on the site you want. Each cookie carries name, value, domain, path, expires (Unix seconds, -1 for a session cookie), size, httpOnly, secure, sameSite ('strict'|'lax'|'none'|'default'), session. Filter with 'domain' and/or 'name'. Pass 'savePath' to write the array to a JSON file instead: the response is then {path,bytes,count,target} with no cookie value in any form, the way to capture a session cookie without putting the credential in the transcript.",
|
|
9392
|
+
params: {
|
|
9393
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9394
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9395
|
+
domain: "Keep only cookies for this domain. A leading dot is ignored on both sides and subdomains match too, so 'example.test' matches '.example.test' and 'app.example.test'. No wildcards.",
|
|
9396
|
+
name: "Keep only the cookie with exactly this name. Exact match, not a substring.",
|
|
9397
|
+
savePath: "Write the cookie array here as JSON and KEEP THE VALUES OUT OF THE RESPONSE: the result is {path,bytes,count,target} only, with no preview or truncation of any value. An absolute path (starting with /) is used as-is; a relative path resolves under the artifact dir (/tmp/cdp-toolkit); missing parents are created. Omit to get the cookies back inline."
|
|
9398
|
+
}
|
|
9399
|
+
},
|
|
9400
|
+
set_cookie: {
|
|
9401
|
+
description: "Write one cookie into the target page's cookie store, INCLUDING httpOnly or secure cookies that document.cookie (and therefore evaluate_script) cannot create. Either 'url' or 'domain' is REQUIRED: the call is refused when neither is given, rather than guessing the page origin. The response is {set:true,target} and never echoes the value back. A 'set:true' is earned, not assumed: Chrome raises an error when it declines the cookie (a domain the url does not belong to, a secure cookie on an insecure origin, an oversized value). On Firefox 'domain' is derived from 'url' when only the url was given (BiDi has no url parameter), and a url with no host such as about:blank or a data URL is an error, not a silent no-op. Read the result back with list_cookies when you need proof.",
|
|
9402
|
+
params: {
|
|
9403
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9404
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9405
|
+
name: "Cookie name. Required and non-empty.",
|
|
9406
|
+
value: "Cookie value. Required. It is not echoed back in the response.",
|
|
9407
|
+
url: "URL the cookie is set for, e.g. 'https://example.com/'. Chrome derives domain, path and secure from it; Firefox derives only the domain from its host. Give this or 'domain'.",
|
|
9408
|
+
domain: "Cookie domain, e.g. 'example.com' or '.example.com' for subdomains. Give this or 'url'. When both are given, this wins on Firefox and Chrome applies its own url plus domain consistency rule.",
|
|
9409
|
+
path: "Cookie path, passed through exactly as given and NOT defaulted to '/': with a 'url' Chrome derives the path from it, so an invented default here would widen a cookie you meant to scope narrowly.",
|
|
9410
|
+
expires: "Expiry as Unix time in SECONDS, matching what list_cookies reports. Omit for a session cookie, which is what both backends do when no expiry is supplied.",
|
|
9411
|
+
httpOnly: "Set the httpOnly flag, making the cookie invisible to document.cookie. Only a protocol write like this one can create such a cookie.",
|
|
9412
|
+
secure: "Set the secure flag. Chrome declines a secure cookie on an insecure origin, and that refusal surfaces as an error.",
|
|
9413
|
+
sameSite: "SameSite attribute, lowercase, matching what list_cookies reports. 'default' means the attribute is not set at all."
|
|
9414
|
+
}
|
|
9415
|
+
},
|
|
9416
|
+
delete_cookies: {
|
|
9417
|
+
description: "Delete the named cookie from the target page's cookie store, httpOnly cookies included. Both 'name' and one of 'url' or 'domain' are REQUIRED: without a site constraint it would delete by name across the whole partition, so it is refused with an error instead. Narrow further with 'path'. The response is {deleted:true,target} and carries NO count, because neither protocol reports how many cookies it removed and a number here would be invented; call list_cookies before and after for a real count. 'deleted:true' means the backend accepted and performed the deletion, not that a matching cookie existed, since deleting an absent cookie succeeds on both backends.",
|
|
9418
|
+
params: {
|
|
9419
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9420
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9421
|
+
name: "Exact cookie name to delete. Required and non-empty. No wildcards: this removes a named cookie, not a swathe of them.",
|
|
9422
|
+
url: "Delete cookies matching this URL, e.g. 'https://example.com/'. Give this or 'domain'. On Firefox only the host is used, because BiDi's filter has no url field.",
|
|
9423
|
+
domain: "Delete cookies with this exact domain. Give this or 'url'.",
|
|
9424
|
+
path: "Narrow the deletion to cookies with this exact path. Omit to match any path allowed by the other constraints."
|
|
9425
|
+
}
|
|
9426
|
+
},
|
|
9427
|
+
take_snapshot: {
|
|
9428
|
+
description: "Captures the page's accessibility tree as an indented text tree, each line prefixed [uid] (a CDP backendDOMNodeId). Every interaction tool (click/hover/fill/etc.) resolves that uid via DOM.resolveNode — run this first to discover uids to act on.",
|
|
9429
|
+
params: {
|
|
9430
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9431
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9432
|
+
interactiveOnly: "When true, emit only interactive/meaningful nodes as a flat list; default false returns the full hierarchical tree."
|
|
9433
|
+
}
|
|
9434
|
+
},
|
|
9435
|
+
click: {
|
|
9436
|
+
description: "Click an element via a synthetic mouse press/release at its scrolled-into-view center. Give exactly one of uid or selector. modifiers (Alt/Control/Meta/Shift) throws on the Firefox backend — use --browser chrome for a modifier-click. clickCount:3 triple-clicks (selects a line/paragraph in most editors).",
|
|
9437
|
+
params: {
|
|
9438
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9439
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9440
|
+
uid: "CDP backendDOMNodeId of the element to click, from take_snapshot. Exactly one of uid or selector.",
|
|
9441
|
+
selector: "CSS selector for the element to click (document.querySelector). Exactly one of uid or selector.",
|
|
9442
|
+
button: "Mouse button: 'left' (default), 'right', or 'middle'.",
|
|
9443
|
+
clickCount: "Number of clicks: 1 (default), 2 = double-click, 3 = triple-click.",
|
|
9444
|
+
modifiers: "Modifier keys held for the click's press and release, e.g. ['Shift']. Non-empty on the Firefox backend throws — not supported over BiDi."
|
|
9445
|
+
}
|
|
9446
|
+
},
|
|
9447
|
+
hover: {
|
|
9448
|
+
description: "Hovers the mouse over an element by dispatching a mouseMoved event at its scrolled-into-view center, firing framework hover handlers. Give exactly one of uid or selector.",
|
|
9449
|
+
params: {
|
|
9450
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9451
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9452
|
+
uid: "CDP backendDOMNodeId of the element to hover, from take_snapshot. Exactly one of uid or selector.",
|
|
9453
|
+
selector: "CSS selector for the element to hover (document.querySelector). Exactly one of uid or selector."
|
|
9454
|
+
}
|
|
9455
|
+
},
|
|
9456
|
+
drag: {
|
|
9457
|
+
description: "Drags from a source element to a destination or by an offset. mode:'mouse' (default) dispatches synthetic mouse press/move/release; at the default steps:2 an HTML5 drop zone (dragover preventDefault) gets ZERO dragover events and refuses the drop. mode:'html5' replays real dragstart/dragEnter/dragOver/drop with the page's own dataTransfer instead — deterministic regardless of pointer path, but CHROME-ONLY (rejected with a clear error on the Firefox backend). 'from' takes uid or selector; destination is exactly one of 'to' (uid/selector/x+y) or 'by' ({dx,dy} offset — sliders, map panning, resize handles).",
|
|
9458
|
+
params: {
|
|
9459
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9460
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9461
|
+
from: "Source element to drag from. Exactly one of uid or selector.",
|
|
9462
|
+
to: "Where the drag ends: exactly one of uid, selector, or x+y. Mutually exclusive with 'by'; exactly one of to/by required.",
|
|
9463
|
+
by: "Offset from the source element's center: at least one of dx/dy (other defaults to 0). Mutually exclusive with 'to'; exactly one of to/by required. For sliders (by:{dx:40}), map panning, resize handles.",
|
|
9464
|
+
mode: "'mouse' (default): synthetic mouse press/move/release — at steps:2 an HTML5 drop zone sees zero dragover events and refuses the drop. 'html5': real HTML5 drag-and-drop, deterministic regardless of pointer path, CHROME-ONLY (rejected on Firefox).",
|
|
9465
|
+
steps: "Number of interpolated mouse-move events between source and destination, evenly spaced, last landing on the destination. Integer 1-500, default 2. Raise for DnD libraries with a movement threshold or per-frame sampling."
|
|
9466
|
+
}
|
|
9467
|
+
},
|
|
9468
|
+
scroll: {
|
|
9469
|
+
description: "Dispatches a wheel/scroll event at an anchor point — element (uid/selector) or x+y, scrolled into view first if an element; omit all three for viewport center. At least one of deltaX/deltaY required: positive deltaY scrolls DOWN, positive deltaX scrolls RIGHT (wheel-event convention — easy to invert). Returns the resolved anchor {x,y} plus the delta actually dispatched.",
|
|
9470
|
+
params: {
|
|
9471
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9472
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9473
|
+
uid: "CDP backendDOMNodeId of the element to scroll into view and anchor at, from take_snapshot. At most one of uid, selector, or x+y.",
|
|
9474
|
+
selector: "CSS selector for the element to anchor at (document.querySelector). At most one of uid, selector, or x+y.",
|
|
9475
|
+
x: "Absolute viewport x-coordinate to anchor at; must be given with y. At most one of uid, selector, or x+y.",
|
|
9476
|
+
y: "Absolute viewport y-coordinate to anchor at; must be given with x. At most one of uid, selector, or x+y.",
|
|
9477
|
+
deltaX: "Horizontal scroll delta; positive scrolls RIGHT. At least one of deltaX/deltaY required.",
|
|
9478
|
+
deltaY: "Vertical scroll delta; positive scrolls DOWN. At least one of deltaX/deltaY required."
|
|
9479
|
+
}
|
|
9480
|
+
},
|
|
9481
|
+
dispatch_mouse: {
|
|
9482
|
+
description: "Dispatches one raw mouse event (move/down/up) at absolute viewport coordinates — the toolkit's lowest-level input primitive. Compose move/down/move/up calls yourself for anything click/drag's fixed sequences can't reach: canvas drag-painting, marquee/rubber-band selection, custom hit-testing widgets. Chrome-only: absent from tools/list under the Firefox backend, never present-and-throwing.",
|
|
9483
|
+
params: {
|
|
9484
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9485
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9486
|
+
action: "Which raw event to dispatch: 'move' (mouseMoved), 'down' (mousePressed), or 'up' (mouseReleased).",
|
|
9487
|
+
x: "Viewport x-coordinate. Required every call — CDP has no 'current pointer position' to default from.",
|
|
9488
|
+
y: "Viewport y-coordinate. Required every call.",
|
|
9489
|
+
button: "Mouse button: 'left' (default), 'right', or 'middle'.",
|
|
9490
|
+
clickCount: "Click-run length for a 'down' or 'up' event (2 = second half of a double-click, 3 = triple-click). Ignored for 'move'; defaults to 1.",
|
|
9491
|
+
modifiers: "Modifier keys held for this one event, e.g. ['Shift']."
|
|
9492
|
+
}
|
|
9493
|
+
},
|
|
9494
|
+
wait_for_download: {
|
|
9495
|
+
description: "Wait for a file download to finish and return it as a real file on disk: {path,suggestedFilename,bytes,url,target}, written under the artifact dir's downloads/. ORDERING RULE, not optional: capture must be ARMED BEFORE the click that starts the download — call wait_for_download{arm:true} first (returns {armed:true,downloadPath,pending}), then click, then call again to collect the file. The download-behavior override is per-connection state Chrome REVERTS the moment the arming client disconnects, and an unarmed headless Chrome denies the download outright, so one triggered before arming is lost. SIDE EFFECT, browser-global: arming redirects EVERY download in this browser (all tabs, all origins) into the toolkit's downloads dir until this server exits — they no longer land in the user's normal Downloads folder. The arm lives on a connection this server holds open (an MCP-server capability): under the one-shot CLI the connection dies with the process and nothing is captured. Chrome-only (capability 'browser.downloads'): absent from tools/list under Firefox.",
|
|
9496
|
+
params: {
|
|
9497
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9498
|
+
target: "Names the tab for the lease check and the echoed target — a download is browser-scoped, so this does not pick which download is returned. Grammar: server instructions.",
|
|
9499
|
+
arm: "Arm download capture and return immediately instead of waiting: {armed:true,downloadPath,pending}. Call this BEFORE the click that triggers the download. 'pending' counts downloads that already completed and have not been collected yet, so an arm call doubles as a peek.",
|
|
9500
|
+
timeoutMs: "How long to wait for a download to complete, in milliseconds. Default 30000. Ignored with arm:true. A download that already completed and was not yet collected is returned immediately, so this only bounds the wait for one still in flight."
|
|
9501
|
+
}
|
|
9502
|
+
},
|
|
9503
|
+
grant_permissions: {
|
|
9504
|
+
description: "Grant browser permissions for an origin up front, so a page asking for geolocation / notifications / clipboard gets an answer instead of a prompt no agent can click. 'permissions' takes CDP PermissionType values ('geolocation','notifications','clipboardReadWrite','camera',...); an unknown name is refused by Chrome, quoting the bad value. Returns {granted,origin,target}, or {reset:true,target} for a reset-only call. Grants are keyed by ORIGIN, not by tab: every tab on that origin is affected, including ones opened later. reset:true clears this server's previous grants first (or instead, when no permissions are given) — CDP's reset is not origin-scoped, so it clears them for every origin at once. The grant lives on a connection this server holds open and Chrome DISCARDS IT when that connection closes: an MCP-server capability, so under the one-shot CLI the grant dies with the process. Chrome-only (capability 'browser.permissions'): absent from tools/list under Firefox, never present-and-throwing.",
|
|
9505
|
+
params: {
|
|
9506
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9507
|
+
target: "Also the origin source when 'origin' is omitted. Grammar: server instructions.",
|
|
9508
|
+
permissions: "CDP PermissionType values to grant, e.g. ['geolocation'] or ['clipboardReadWrite','clipboardSanitizedWrite']. Required unless reset:true. An empty array is refused rather than treated as a successful no-op.",
|
|
9509
|
+
origin: "Origin the grant applies to, e.g. 'https://example.com'. Defaults to the target tab's own origin. Required explicitly when that tab has no grantable origin (data:, blob:, about:blank all serialize to the opaque origin 'null'), which is refused with a message naming the tab's url.",
|
|
9510
|
+
reset: "Clear this server's previous permission grants (Browser.resetPermissions). With 'permissions' it resets FIRST and then grants, so the result is exactly the listed permissions; on its own it is a reset-only call answering {reset:true}. Not scoped to 'origin': CDP resets every origin at once."
|
|
9511
|
+
}
|
|
9512
|
+
},
|
|
9513
|
+
fill: {
|
|
9514
|
+
description: "Fills an element by focusing it, clearing existing content, then inserting value via Input.insertText (atomic paste-like commit, not per-character keystrokes — won't fire per-keypress handlers). Give exactly one of uid or selector.",
|
|
9515
|
+
params: {
|
|
9516
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9517
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9518
|
+
uid: "CDP backendDOMNodeId of the field to fill, from take_snapshot. Exactly one of uid or selector.",
|
|
9519
|
+
selector: "CSS selector for the field to fill (document.querySelector). Exactly one of uid or selector.",
|
|
9520
|
+
value: "Text value to set; the field is cleared first, overwriting existing content."
|
|
9521
|
+
}
|
|
9522
|
+
},
|
|
9523
|
+
fill_form: {
|
|
9524
|
+
description: "Fills multiple form fields in one call; each is focused, cleared, then set via Input.insertText (overwrites existing content, same as fill). Each entry in the non-empty 'fields' array takes exactly one of uid or selector plus a string value.",
|
|
9525
|
+
params: {
|
|
9526
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9527
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9528
|
+
fields: "Non-empty array of fields to fill, each with exactly one of uid or selector plus a string value."
|
|
9529
|
+
}
|
|
9530
|
+
},
|
|
9531
|
+
type_text: {
|
|
9532
|
+
description: "Focuses an element and appends text via Input.insertText without clearing first — closest primitive to typing, but still atomic (not per-character keystrokes). Give exactly one of uid or selector.",
|
|
9533
|
+
params: {
|
|
9534
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9535
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9536
|
+
uid: "CDP backendDOMNodeId of the element to type into, from take_snapshot. Exactly one of uid or selector.",
|
|
9537
|
+
selector: "CSS selector for the element to type into (document.querySelector). Exactly one of uid or selector.",
|
|
9538
|
+
text: "Text to insert; appended to existing content rather than overwriting it."
|
|
9539
|
+
}
|
|
9540
|
+
},
|
|
9541
|
+
press_key: {
|
|
9542
|
+
description: "Dispatches a keyDown/keyUp pair for one key with optional modifiers. 'key' is a named key (Enter, Tab, Escape, ArrowDown, Backspace, etc.) or a single printable character — the named-key table is curated, with no F-keys, numpad, or IME support.",
|
|
9543
|
+
params: {
|
|
9544
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9545
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9546
|
+
key: "Key to press: a named key (Enter, Tab, Escape, ArrowDown, Backspace, ...) or a single printable character.",
|
|
9547
|
+
modifiers: "Modifier names held during the press: 'Control'/'Ctrl', 'Shift', 'Alt', 'Meta'/'Cmd'."
|
|
9548
|
+
}
|
|
9549
|
+
},
|
|
9550
|
+
upload_file: {
|
|
9551
|
+
description: "Attaches one or more files to an <input type=file> element via DOM.setFileInputFiles. Give exactly one of uid or selector for the input; 'files' is an array of absolute path(s) — wrap a single path in an array too.",
|
|
9552
|
+
params: {
|
|
9553
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9554
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9555
|
+
uid: "CDP backendDOMNodeId of the file input element, from take_snapshot. Exactly one of uid or selector.",
|
|
9556
|
+
selector: "CSS selector for the file input element (document.querySelector). Exactly one of uid or selector.",
|
|
9557
|
+
files: 'Absolute path(s) to attach to the <input type=file>, as an array — wrap a single path too, e.g. ["/tmp/a.pdf"]. Array-only because some model APIs (Google Gemini function calling) reject union-typed parameters.'
|
|
9558
|
+
}
|
|
9559
|
+
},
|
|
9560
|
+
take_screenshot: {
|
|
9561
|
+
description: "Captures the viewport (default), the full scrollable page (fullPage), or one element (uid or selector, mutually exclusive) via CDP Page.captureScreenshot. Past 16384 device px per side Chrome can hang rather than refuse, so size is checked first via Page.getLayoutMetrics; an oversized capture is auto-tiled into vertical bands stitched losslessly into one PNG (see tile) instead of wedging the tab. Writes PNG/JPEG to /tmp/cdp-toolkit (override savePath, dir auto-created); returns {path,bytes,format,target,scale} plus width/height measured from the encoded bytes (omitted if undecodable). renderSize/renderRestored(+renderRestoreError) accompany a renderWidth/renderHeight capture, tiled/bands a banded one. returnBase64 adds raw bytes to the result but is refused on a banded capture. quality applies to jpeg only.",
|
|
9562
|
+
params: {
|
|
9563
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9564
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9565
|
+
format: "Image format, default png. quality applies only to jpeg.",
|
|
9566
|
+
quality: "JPEG quality 0-100, default 80; ignored for png.",
|
|
9567
|
+
fullPage: "Capture the full scrollable height (via Page.getLayoutMetrics), not just the viewport.",
|
|
9568
|
+
scale: "Output-pixel multiplier for this capture only (0<scale<=8, default 1): output px = ceil(css px x scale x devicePixelRatio); the page is never told anything changed. Chrome only (screenshot.scale) — Firefox BiDi has no scale param, use emulate{deviceScaleFactor} then scale:1. A projection over 16384 device px/side is refused up front, naming the largest scale that fits.",
|
|
9569
|
+
renderWidth: "Emulates this viewport width (CSS px, 1-16384) for one capture, then restores it. Required with renderHeight. Unlike scale, this changes what the page believes (media queries re-flow) — e.g. capture a responsive page at 1920x1080 from a differently-sized tab. Restore only works for an override this toolkit itself set; check result.renderRestored (false = still emulated, fix via emulate). Works on both backends (capability screenshot.renderSize).",
|
|
9570
|
+
renderHeight: "Emulates this viewport height (CSS px, 1-16384) for one capture. Required with renderWidth — a viewport is two numbers. A narrow renderWidth often reflows pages TALLER, which is the usual way a render-size capture trips the 16384px encode limit.",
|
|
9571
|
+
tile: "Whether to allow vertical-band stitching: omitted=AUTO (band only if a single shot wouldn't fit), false=never band (refuse instead), true=always band (Chrome-only capability). Banded output is PNG-only, can't returnBase64, and only bands on HEIGHT (oversized WIDTH is refused, not split). Bands are a faithful crop, but lazy/virtualized content the real viewport never scrolled to renders blank.",
|
|
9572
|
+
uid: "Element to clip to: a backendDOMNodeId from take_snapshot. Mutually exclusive with selector.",
|
|
9573
|
+
selector: "CSS selector to clip the capture to. Mutually exclusive with uid.",
|
|
9574
|
+
savePath: "Override the output path (default /tmp/cdp-toolkit/screenshot-<id>-<stamp>.<ext>, stamped at capture START). Directory is created from this path's dirname.",
|
|
9575
|
+
returnBase64: "Also return raw base64 bytes in the result. Refused on a banded capture (see tile) — a stitched image can run to hundreds of MB; read the file at the returned path instead."
|
|
9576
|
+
}
|
|
9577
|
+
},
|
|
9578
|
+
emulate: {
|
|
9579
|
+
description: "Applies any subset of Chrome emulation overrides in one call: device metrics (width+height together, +deviceScaleFactor/mobile), userAgent, cpuThrottlingRate(>=1), media type+features, networkConditions. Device-metrics overrides PERSIST on the target until cleared or the renderer navigates/reloads; every other override is session-scoped and resets when this call's connection closes. clearOverrides:true resets everything (ignoring other fields) and, as of 1.9.2, genuinely clears a device-metrics override set by a DIFFERENT process — Chrome's clearDeviceMetricsOverride is normally a no-op unless the clearing connection also set the override, so the driver re-asserts the tab's current size first, then clears, throwing rather than reporting cleared:true if it can't verify.",
|
|
9580
|
+
params: {
|
|
9581
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9582
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9583
|
+
width: "Device-metrics viewport width in CSS px. Must be paired with height.",
|
|
9584
|
+
height: "Device-metrics viewport height in CSS px. Must be paired with width.",
|
|
9585
|
+
deviceScaleFactor: "Device pixel ratio for the device-metrics override; 0 = platform default.",
|
|
9586
|
+
mobile: "Emulate a mobile device (viewport meta, scrollbars, etc.) for the device-metrics override.",
|
|
9587
|
+
userAgent: "User-Agent string override (Emulation.setUserAgentOverride).",
|
|
9588
|
+
cpuThrottlingRate: "CPU throttling multiplier: 1=none, 2=2x slower, etc. Must be >=1.",
|
|
9589
|
+
media: "Emulated CSS media type: 'screen' | 'print' | '' (clear).",
|
|
9590
|
+
mediaFeatures: "Emulated media features, e.g. [{name:'prefers-color-scheme', value:'dark'}].",
|
|
9591
|
+
networkConditions: "Network overrides applied via Network.emulateNetworkConditions.",
|
|
9592
|
+
clearOverrides: "Reset every override (metrics, UA, CPU, media, network) to browser default; ignores all other fields when true."
|
|
9593
|
+
}
|
|
9594
|
+
},
|
|
9595
|
+
resize_page: {
|
|
9596
|
+
description: "Sets the page's device-metrics width/height (the narrow case of emulate), optionally deviceScaleFactor/mobile, then verifies by reading back window.innerWidth/innerHeight after applying. Requires positive width and height. The override PERSISTS on the target until cleared (emulate{clearOverrides:true}) or the renderer navigates/reloads.",
|
|
9597
|
+
params: {
|
|
9598
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9599
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9600
|
+
width: "Viewport width in CSS px (required, must be positive).",
|
|
9601
|
+
height: "Viewport height in CSS px (required, must be positive).",
|
|
9602
|
+
deviceScaleFactor: "Device pixel ratio; 0 = platform default.",
|
|
9603
|
+
mobile: "Emulate a mobile device for the device-metrics override."
|
|
9604
|
+
}
|
|
9605
|
+
},
|
|
9606
|
+
handle_dialog: {
|
|
9607
|
+
description: "Wait for the next JavaScript dialog (alert/confirm/prompt/beforeunload) on a page and respond via Page.handleJavaScriptDialog, accepting or dismissing it. Default mode resolves with the first handled dialog or throws on timeout; set autoMs to handle every dialog opening during a fixed window and resolve with the list. Trigger the dialog out-of-band (e.g. click a button) — a blocking dialog freezes the renderer, so it cannot be triggered inline.",
|
|
9608
|
+
params: {
|
|
9609
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9610
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9611
|
+
accept: "Whether to accept (OK) or dismiss (Cancel) the dialog.",
|
|
9612
|
+
promptText: "Text to enter for a prompt() dialog when accepting.",
|
|
9613
|
+
timeoutMs: "How long to wait for the next dialog, in milliseconds (default 15000).",
|
|
9614
|
+
autoMs: "Auto-handle mode: keep handling every dialog that opens for this many milliseconds, then resolve with the list of handled dialogs (an empty list is valid; never throws on 'no dialog')."
|
|
9615
|
+
}
|
|
9616
|
+
},
|
|
9617
|
+
list_console_messages: {
|
|
9618
|
+
description: "Read console output (logs, warnings, exceptions) captured for the target. Reads the existing shared buffer by default (empty if no capture ran); reload:true reloads and records a fresh capture (console+network together, so a network reload never wipes console history). WORKER capture (Chrome, Capability 'worker.targets'): a worker: target records an MV3 background service worker -- its console.log arrives as Runtime.consoleAPICalled, its outbound requests from CDP's Network domain on the worker's own session -- so the two tricks callers try first fail for plain JS reasons, not worker ones: a value bound at module top level is not visible from evaluate_script's global scope, and assigning self.fetch cannot rebind a fetch the module already captured. A worker has no reload: reload:true means 'listen for durationMs while it runs', so trigger its work (tool call, message, alarm) during the window; a worker woken by the call already ran its top-level code, so a startup message can be missed. SIDE EFFECT: the CDP session KEEPS THE WORKER ALIVE for the capture (an idle MV3 worker is evicted in seconds); Chrome resumes evicting after.",
|
|
9619
|
+
params: {
|
|
9620
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9621
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', '<targetId>'; plus 'worker:<substring>' to reach a service/shared worker (e.g. an MV3 extension background worker). The worker: arm is CHROME-ONLY (Capability 'worker.targets'). Grammar: see server instructions.",
|
|
9622
|
+
reload: "Record fresh by reloading the page and capturing a window. Default false (read existing buffer). With a worker: target nothing reloads -- records for durationMs while the worker runs and keeps it alive until the capture stops.",
|
|
9623
|
+
durationMs: "Capture window for reload mode, in ms. Default 2500.",
|
|
9624
|
+
wake: "Worker targets only, when starting a capture. Default true: an idle-evicted MV3 service worker exists in no target listing, so it is started first (ServiceWorker.startWorker) and re-confirmed; false fails fast. Rejected on a page target, a bare target id, or a read-only call. See server instructions."
|
|
9625
|
+
}
|
|
9626
|
+
},
|
|
9627
|
+
get_console_message: {
|
|
9628
|
+
description: "Return one console entry by zero-based index from the target's existing console buffer. Throws if the index is out of range; run list_console_messages (optionally reload:true) first to populate the buffer.",
|
|
9629
|
+
params: {
|
|
9630
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9631
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9632
|
+
index: "Zero-based index into the parsed console entries. Default 0."
|
|
9633
|
+
}
|
|
9634
|
+
},
|
|
9635
|
+
list_network_requests: {
|
|
9636
|
+
description: "Return correlated network rows (one per requestId; status/headers/state) for the target. Reads the existing buffer by default; reload:true records a fresh both-domains capture window. filterUrl keeps only URLs containing a substring. WORKER capture (Chrome, Capability 'worker.targets'): a worker: target records an MV3 background service worker's outbound requests from CDP's Network domain on the worker's own session -- what the code ACTUALLY SENT -- so the two tricks callers try first fail for plain JS reasons, not worker ones: a value bound at module top level is not visible from evaluate_script's global scope, and assigning self.fetch cannot rebind a fetch the module already captured. A worker has no reload: reload:true means 'listen for durationMs while it runs', so trigger its work (tool call, message, alarm) during the window; a worker woken by the call already ran its top-level code, so a startup request can be missed. SIDE EFFECT: the CDP session KEEPS THE WORKER ALIVE for the capture (an idle MV3 worker is evicted in seconds); Chrome resumes evicting after.",
|
|
9637
|
+
params: {
|
|
9638
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9639
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', '<targetId>'; plus 'worker:<substring>' to reach a service/shared worker (e.g. an MV3 extension background worker). The worker: arm is CHROME-ONLY (Capability 'worker.targets'). Grammar: see server instructions.",
|
|
9640
|
+
reload: "Record fresh by reloading the page and capturing a window. Default false (read existing buffer). With a worker: target nothing reloads -- records for durationMs while the worker runs and keeps it alive until the capture stops.",
|
|
9641
|
+
durationMs: "Capture window for reload mode, in ms. Default 2500.",
|
|
9642
|
+
filterUrl: "Return only requests whose URL contains this substring.",
|
|
9643
|
+
wake: "Worker targets only, when starting a capture. Default true: an idle-evicted MV3 service worker exists in no target listing, so it is started first (ServiceWorker.startWorker) and re-confirmed; false fails fast. Rejected on a page target, a bare target id, or a read-only call. See server instructions."
|
|
9644
|
+
}
|
|
9645
|
+
},
|
|
9646
|
+
get_network_request: {
|
|
9647
|
+
description: "Return one network request (matched by exact requestId, else url substring) with status/headers. Requires requestId or url (throws otherwise). includeBody:true drives a fresh capture (page reload, or worker listen window) matched by url ONLY -- a fresh capture re-mints requestIds, so a carried-over requestId returns metadata plus bodyUnavailableReason. WORKER capture (Chrome, Capability 'worker.targets'): a worker: target records an MV3 background service worker's outbound requests from CDP's Network domain on the worker's own session -- what the code ACTUALLY SENT -- so the two tricks callers try first fail for plain JS reasons, not worker ones: a value bound at module top level is not visible from evaluate_script's global scope, and assigning self.fetch cannot rebind a fetch the module already captured. A worker has no reload: reload means 'listen for durationMs while it runs', so trigger its work (tool call, message, alarm) during the window; a worker woken by the call already ran its top-level code, so a startup request can be missed. SIDE EFFECT: the CDP session KEEPS THE WORKER ALIVE for the capture (an idle MV3 worker is evicted in seconds); Chrome resumes evicting after.",
|
|
9648
|
+
params: {
|
|
9649
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9650
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', '<targetId>'; plus 'worker:<substring>' to reach a service/shared worker (e.g. an MV3 extension background worker). The worker: arm is CHROME-ONLY (Capability 'worker.targets'). Grammar: see server instructions.",
|
|
9651
|
+
requestId: "Match by exact requestId (metadata only; cannot fetch a body, since a reload re-mints requestIds).",
|
|
9652
|
+
url: "Match by URL substring (first match). Required for body fetch (includeBody), since url is stable across reload.",
|
|
9653
|
+
includeBody: "Also fetch the response body; drives a fresh capture and requires the url selector.",
|
|
9654
|
+
durationMs: "Capture window for the body-fetch reload, in ms. Default 2500.",
|
|
9655
|
+
wake: "Worker targets only, when starting a capture. Default true: an idle-evicted MV3 service worker exists in no target listing, so it is started first (ServiceWorker.startWorker) and re-confirmed; false fails fast. Rejected on a page target, a bare target id, or a read-only call. See server instructions."
|
|
9656
|
+
}
|
|
9657
|
+
},
|
|
9658
|
+
performance_start_trace: {
|
|
9659
|
+
description: "Starts a CDP trace recording on the target and holds the recording connection in-process; you MUST call performance_stop_trace from the SAME PROCESS to end it, or use performance_trace instead for a robust cross-call trace. Throws if a trace is already in progress for this target.",
|
|
9660
|
+
params: {
|
|
9661
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9662
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9663
|
+
categories: "Trace categories to record. Defaults to timeline + user-timing + loading + disabled-by-default timeline tracks carrying LCP/LayoutShift/RunTask."
|
|
9664
|
+
}
|
|
9665
|
+
},
|
|
9666
|
+
performance_stop_trace: {
|
|
9667
|
+
description: "Stops the in-process trace started by performance_start_trace and writes it as JSON under /tmp/cdp-toolkit, returning {path,bytes,events,metrics}. Throws if no live trace exists in THIS process (e.g. start ran in a different process) — use performance_trace instead. The target arg is accepted only for API symmetry; at most one trace is ever live per process.",
|
|
9668
|
+
params: {
|
|
9669
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9670
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions."
|
|
9671
|
+
}
|
|
9672
|
+
},
|
|
9673
|
+
performance_analyze_insight: {
|
|
9674
|
+
description: "Reads a trace JSON file (from performance_trace/performance_stop_trace) at tracePath and returns headline metrics: FCP/LCP/CLS/TBT, long tasks, layout shifts. Requires an EXPLICIT tracePath — there is no implicit 'latest trace'. Numbers approximate DevTools's insight analyzer (no main-thread attribution or frame-scoped LCP).",
|
|
9675
|
+
params: {
|
|
9676
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9677
|
+
tracePath: "Path to a trace JSON file (bare array or {traceEvents:[...]}) written by performance_trace or performance_stop_trace. Required."
|
|
9678
|
+
}
|
|
9679
|
+
},
|
|
9680
|
+
performance_trace: {
|
|
9681
|
+
description: "RECOMMENDED entry point: one-shot trace that starts tracing, optionally reloads or navigates the page, waits durationMs (default 3000ms), stops, and writes JSON under /tmp/cdp-toolkit — returns {path,bytes,events,metrics,target}. Holds one connection open for the whole window, so unlike start/stop it is NOT limited to a single process.",
|
|
9682
|
+
params: {
|
|
9683
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9684
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9685
|
+
durationMs: "How long to record after the optional reload/navigate, in ms. Default 3000.",
|
|
9686
|
+
reload: "Reload the page after starting the trace, to capture full navigation timing.",
|
|
9687
|
+
navigateTo: "Navigate to this URL after starting the trace (alternative to reload).",
|
|
9688
|
+
categories: "Trace categories to record. Defaults to timeline + user-timing + loading + disabled-by-default timeline tracks carrying LCP/LayoutShift/RunTask."
|
|
9689
|
+
}
|
|
9690
|
+
},
|
|
9691
|
+
start_screen_recording: {
|
|
9692
|
+
description: "Starts recording the target tab to video via CDP Page.startScreencast, holding one persistent connection and spooling every frame to disk — MUST be paired with stop_screen_recording WITHIN THE SAME PROCESS (frames are connection-scoped and cannot be reattached from another process, so this only works under the MCP server, not the one-process-per-call CLI). Chrome only: WebDriver BiDi has no screencast primitive, so both tools are absent under --browser firefox. Frames arrive ON REPAINT not on a clock (variable rate); each is timestamped into a ledger that stop_screen_recording turns into per-frame display durations, so a still page holds one long frame instead of racing. ffmpeg is probed here (not at stop) so a missing encoder fails before frames are captured and thrown away. Throws if the target already has a recording in progress; different targets record concurrently.",
|
|
9693
|
+
params: {
|
|
9694
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9695
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9696
|
+
format: "Frame format, default jpeg (much smaller per repaint); png is lossless. quality applies to jpeg only.",
|
|
9697
|
+
quality: "JPEG frame quality 0-100. Ignored for png; omitted leaves Chrome's own default.",
|
|
9698
|
+
maxWidth: "Caps the streamed frame width in px; also pins frame size if the viewport may change mid-recording.",
|
|
9699
|
+
maxHeight: "Caps the streamed frame height in px.",
|
|
9700
|
+
everyNthFrame: "Capture only every Nth repaint (1=every frame), to shrink spool size on a busy page; per-frame durations keep playback at wallclock speed either way.",
|
|
9701
|
+
bringToFront: "Activate the tab (Page.bringToFront) before recording, default false. A backgrounded/occluded tab may never repaint, yielding a 0-frame recording."
|
|
9702
|
+
}
|
|
9703
|
+
},
|
|
9704
|
+
stop_screen_recording: {
|
|
9705
|
+
description: "Stops the recording started by start_screen_recording, assembling spooled frames into an MP4 via ffmpeg with PER-FRAME durations (frame N held until N+1 painted; last frame held until this call) — capped at 25fps by ffmpeg's concat demuxer, so frames under 40ms apart are deliberately coalesced (frameCount=captured, encodedFrames=what reached the video, never silently dropped). Returns {path,bytes,durationMs,frameCount,encodedFrames,codec,encoder,width,height,droppedFrames,target}; durationMs sums encoded durations, the file runs one 40ms step longer (final frame repeated). Encoder ladder (probed at start): hevc_videotoolbox>h264_videotoolbox>libx265>libx264 (+hvc1 tag, faststart, yuv420p, even dims). target: omit with one recording in flight, required with several (avoids guessing which to stop). Throws if nothing is recording in this process, or if 0 frames arrived (no silent empty video). On ffmpeg failure the spooled frames are KEPT — spool path + exact command are in the error.",
|
|
9706
|
+
params: {
|
|
9707
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9708
|
+
target: "Which recording to stop — 'active' valid only when exactly one recording is in flight. Grammar: server instructions.",
|
|
9709
|
+
savePath: "Override the output path (default /tmp/cdp-toolkit/screen-recording-<targetIdShort>-<stamp>.mp4)."
|
|
9710
|
+
}
|
|
9711
|
+
},
|
|
9712
|
+
take_heapsnapshot: {
|
|
9713
|
+
description: "Captures a V8 heap snapshot of the target page over CDP and writes it as a .heapsnapshot JSON file (loadable in the DevTools Memory panel) under /tmp/cdp-toolkit unless savePath is given. Returns {path,bytes,chunks,target} only — does NOT parse or summarize the snapshot.",
|
|
9714
|
+
params: {
|
|
9715
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9716
|
+
target: "Page selector: 'active' (default), 'index:N', 'url:<substr>', 'title:<substr>', 'label:<name>', or a 32-hex '<targetId>'. Grammar: see server instructions.",
|
|
9717
|
+
savePath: "Override the output path. Absolute paths (starting with /) are used as-is; relative paths resolve under the artifact dir (/tmp/cdp-toolkit). Defaults to an auto-named take_heapsnapshot-<targetId>-<timestamp>.heapsnapshot file."
|
|
9718
|
+
}
|
|
9719
|
+
},
|
|
9720
|
+
lighthouse_audit: {
|
|
9721
|
+
description: "Runs a Lighthouse audit against a URL by shelling out to `npx --yes lighthouse` (the toolkit's only non-CDP tool) — it attaches to the already-running Chrome and audits its OWN about:blank tab, NOT any live user tab you've navigated. Writes a JSON report under /tmp/cdp-toolkit; returns {path,bytes} plus per-category scores (0..1 or null).",
|
|
9722
|
+
params: {
|
|
9723
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9724
|
+
url: "The URL to audit. Required — never points at a user tab implicitly.",
|
|
9725
|
+
categories: 'Lighthouse categories to run (--only-categories). Defaults to the full set, e.g. ["performance"] or ["performance","accessibility","seo"].',
|
|
9726
|
+
savePath: "Override the report output path; defaults to a timestamped file under /tmp/cdp-toolkit.",
|
|
9727
|
+
formFactor: '"desktop" (default, uses --preset=desktop to avoid heavy mobile throttling) or "mobile".',
|
|
9728
|
+
timeoutMs: "Overall budget for the lighthouse process, in ms. Default 120000."
|
|
9729
|
+
}
|
|
9730
|
+
},
|
|
9731
|
+
mock_request: {
|
|
9732
|
+
description: "Register a mock rule on a target's persistent fake-backend session (CDP Fetch domain): match requests by urlPattern and fulfill with a canned response, fail (abort), or continue -- optionally with fault injection (delayMs/failRate). The session survives reloads/navigations and lives until clear_mocks; call repeatedly to mock several endpoints on one target. reload:true applies it immediately. Persistent across calls only via the MCP server, not the one-shot CLI.",
|
|
9733
|
+
params: {
|
|
9734
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9735
|
+
target: "Which page's mock session. Defaults to the active page. Grammar: server instructions.",
|
|
9736
|
+
urlPattern: `CDP Fetch urlPattern glob: '*' any run of chars, '?' exactly one, '\\' escapes. Only matching URLs are paused. e.g. "*/api/users*".`,
|
|
9737
|
+
action: 'What to do with a matched request. Default "fulfill".',
|
|
9738
|
+
status: "fulfill: HTTP status for the canned response. Default 200.",
|
|
9739
|
+
body: "fulfill: response body string (base64-encoded for CDP internally).",
|
|
9740
|
+
contentType: 'fulfill: Content-Type header. Default "application/json".',
|
|
9741
|
+
headers: 'fulfill: extra response headers (name->value); override Content-Type case-insensitively. Add "Access-Control-Allow-Origin" for cross-origin fetches.',
|
|
9742
|
+
errorReason: 'fail: CDP Network.ErrorReason, e.g. "Failed" (default), "BlockedByClient", "ConnectionRefused", "TimedOut".',
|
|
9743
|
+
method: 'Only mock this HTTP method (e.g. "POST"); others pass through.',
|
|
9744
|
+
delayMs: "Fault injection: artificial latency in ms before responding.",
|
|
9745
|
+
failRate: "Fault injection: probability 0..1 of failing a matched request regardless of action.",
|
|
9746
|
+
reload: "Reload the target after arming so the mock catches traffic immediately."
|
|
9747
|
+
}
|
|
9748
|
+
},
|
|
9749
|
+
list_mocks: {
|
|
9750
|
+
description: "List active fake-backend sessions (one per target) with their rules and hit counts. Prunes sessions whose tab has closed.",
|
|
9751
|
+
params: {
|
|
9752
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9753
|
+
target: "Unused filter placeholder; returns all active sessions."
|
|
9754
|
+
}
|
|
9755
|
+
},
|
|
9756
|
+
clear_mocks: {
|
|
9757
|
+
description: "Tear down fake-backend sessions (Fetch.disable + close the connection). Clears the resolved target's session by default, or every active session with all:true.",
|
|
9758
|
+
params: {
|
|
9759
|
+
lease: "Lease token from claim_page. Omit for a tab this process holds; required for a tab held by another process or one claimed explicitly. Auto-acquired under CDP_REQUIRE_LEASE (then pass target, not lease). See server instructions.",
|
|
9760
|
+
target: "Which page's mock session to clear. Defaults to the active page; ignored when all:true. Grammar: server instructions.",
|
|
9761
|
+
all: "Clear every active mock session instead of just the resolved target's."
|
|
9762
|
+
}
|
|
9763
|
+
},
|
|
9764
|
+
claim_page: {
|
|
9765
|
+
description: "Take exclusive ownership of a browser tab, returning an opaque lease token (needed once under CDP_REQUIRE_LEASE for any tab you drive). Two modes: FRESH TAB (no target - opens one, optionally at url, and claims it: 'give me my own tab' in one call) and TAKEOVER (target - claims an already-open tab, e.g. the human's, resolving the selector against the live page list, creating nothing). The opened flag is true only when this call created the tab, and release_page consults that record, so a taken-over tab is left open on release. Refused from the CLI (its per-call process would make the lease instantly reclaimable). The answer carries humanActiveMs, ms since input this server did not dispatch; null is NO DATA (no activity beacon, or every input was this server's own) and never means 'no human'; absent on a backend that cannot answer. On takeover of a tab a human used within 30s it adds contention, a warning - but THE CLAIM IS NEVER REFUSED FOR THIS: takeover is its purpose, you already hold the lease; it only warns you're fighting a live person, so open your own tab or ask first. Limits: input inside a cross-origin iframe is invisible, and a second MCP server's clicks read as human.",
|
|
9766
|
+
params: {
|
|
9767
|
+
target: "Take over an already-open tab (e.g. one the human has open). Resolved against the LIVE page list only, so it never opens a tab — a selector matching nothing is an error. Left open on release. Refused if another live process holds it (including a lease auto-acquired under CDP_REQUIRE_LEASE): takes over unleased human tabs, never steals from a live agent. Mutually exclusive with targetId. Selector grammar: server instructions.",
|
|
9768
|
+
targetId: "Exact target id (not a selector) of an already-open page to claim instead of opening one. Back-compat only; prefer target, which also accepts an exact id. Mutually exclusive with target.",
|
|
9769
|
+
url: "When opening a fresh tab, navigate it here. Ignored when target or targetId is given.",
|
|
9770
|
+
label: "Agent label recorded on the lease; surfaced in conflict errors and list_leases. Defaults to pid-<pid>.",
|
|
9771
|
+
ttlMs: "How long the lease survives without use before it is reclaimable. Defaults to CDP_LEASE_TTL_MS, else 900000 (15min); every checked call refreshes it."
|
|
9772
|
+
}
|
|
9773
|
+
},
|
|
9774
|
+
release_page: {
|
|
9775
|
+
description: "Give a lease back, closing the tab only if this toolkit opened it. Take exactly one of lease (the token) or target (a selector for a tab this process holds - use this to release a lease the gate acquired for you automatically, since that path never handed you a token). A tab with a creation record from this toolkit is closed; a tab that was already open and merely claimed is released and left alone - override either way with close. Idempotent: an already-released, reclaimed, or expired lease reports released:false and closes nothing (by then the tab may belong to another agent). Answers {released, closed, targetId}.",
|
|
9776
|
+
params: {
|
|
9777
|
+
lease: "Token from claim_page / new_page{claim:true}. Mutually exclusive with 'target'. Under CDP_REQUIRE_LEASE an auto-acquired lease never produced a token — give 'target' instead.",
|
|
9778
|
+
target: "A tab THIS process holds (grammar: server instructions). Mutually exclusive with 'lease'. Refused if another process holds the tab.",
|
|
9779
|
+
close: "Force the close decision instead of letting the creation record decide: true closes even a tab this toolkit did not open; false keeps an agent-created tab open. Omit to close only tabs this toolkit created."
|
|
9780
|
+
}
|
|
9781
|
+
},
|
|
9782
|
+
list_leases: {
|
|
9783
|
+
description: "Enumerate every active lease for diagnosis - backend, target id, label, pid, createdAt, lastUsedAt, ttlMs, whether the owning process is alive, and whether the lease is reclaimable and why. No token required; it never returns the lease nonce, so it cannot be used to forge one. An unreadable or unparseable lease row instead carries unreadable, with label, pid and timestamps zeroed and stale forced false (an unreadable lease must never read as free to take). Under CDP_REQUIRE_LEASE it reaps abandoned agent tabs exactly as list_pages does, into an additive reaped array, omitting their rows. Where the tab can answer, a row also carries humanActiveMs, ms since input this server did not dispatch - note lastUsedAt tracks TOOLKIT calls only, so a tab a person has typed in for ten minutes looks idle, which is what this exposes; the field is absent, never null, when the tab cannot answer, and that absence means 'no answer', never 'nobody is there'. idleMs (now - lastUsedAt) and expiresAt (lastUsedAt + ttlMs) are computed fresh each call and omitted on an unreadable row.",
|
|
9784
|
+
params: {}
|
|
9785
|
+
}
|
|
9786
|
+
};
|
|
9787
|
+
|
|
8894
9788
|
// src/mcp.ts
|
|
8895
|
-
var VERSION = "
|
|
9789
|
+
var VERSION = "2.0.0";
|
|
8896
9790
|
var { kind: BROWSER, endpoint: FIREFOX_ENDPOINT } = resolveBackend(process.argv.slice(2));
|
|
8897
9791
|
var AVAILABILITY = toolAvailability(BROWSER);
|
|
8898
9792
|
var AVAILABLE_NAMES = new Set(AVAILABILITY.available);
|
|
@@ -8910,19 +9804,119 @@ function auditCoverage() {
|
|
|
8910
9804
|
}
|
|
8911
9805
|
var INSTRUCTIONS = [
|
|
8912
9806
|
"cdp-toolkit drives a real browser over Chrome DevTools Protocol (or Firefox WebDriver-BiDi): open and drive pages, click/fill/type, screenshot and accessibility-snapshot, read console + network, set cookies, emulate devices, run Lighthouse and performance traces, record screencasts. Conventions shared across its tools:",
|
|
9807
|
+
"TOOL AVAILABILITY: the server starts on the core profile (12 everyday tools); the rest are organized into groups you can discover and activate with `browser_tools` (or start with CDP_TOOL_PROFILE=full for everything at once). `describe_tool` returns full docs for any tool by name, including hidden ones. Hidden tools are still callable by name even while unlisted.",
|
|
8913
9808
|
"TARGET SELECTOR (the `target` param, unless a tool says otherwise): 'active' (default = first page) | 'index:N' (0-based) | 'url:<substr>' | 'title:<substr>' | 'label:<name>' (exact, from the origin ledger or a live lease) | a 32-hex '<targetId>'. Four Chrome-only tools (evaluate_script, list_network_requests, get_network_request, list_console_messages) also accept 'worker:<substr>' to reach a service/shared worker — e.g. an MV3 extension's background worker (worker:<extension-id> or worker:background.js); an idle-evicted worker is started first (see each tool's `wake`).",
|
|
8914
9809
|
"LEASES (the `lease` param): claim_page, and new_page{claim:true}, mint an opaque token. Omit it for a tab THIS process already holds. It is required for a tab held by ANOTHER process, or one claimed explicitly. Under CDP_REQUIRE_LEASE the gate auto-acquires a lease for any tab this process drives — no token is surfaced, so pass `target`, not `lease` — while an explicit claim:true still demands its token on every later call. Without CDP_REQUIRE_LEASE an unleased tab needs no token at all.",
|
|
8915
9810
|
"ORIGIN: list_pages and list_leases tag each tab's `origin` as 'agent' (this toolkit created it) or 'unknown' — never 'human', because the toolkit cannot prove a person opened a tab. An 'agent' tab stays findable after its creator releases the lease or dies."
|
|
8916
9811
|
].join(`
|
|
8917
9812
|
|
|
8918
9813
|
`);
|
|
8919
|
-
var
|
|
8920
|
-
|
|
8921
|
-
|
|
9814
|
+
var START_PROFILE = process.env.CDP_TOOL_PROFILE === "full" ? "full" : "core";
|
|
9815
|
+
var activeGroups = new Set(PROFILES[START_PROFILE]);
|
|
9816
|
+
var META_TOOLS = [
|
|
9817
|
+
{
|
|
9818
|
+
name: "browser_tools",
|
|
9819
|
+
description: "Manage which cdp-toolkit tool groups are exposed (progressive disclosure). Most tools are hidden until their group is activated; activating one reveals its tools via tools/list_changed. Use action:list_groups first to see what exists.",
|
|
9820
|
+
inputSchema: {
|
|
9821
|
+
type: "object",
|
|
9822
|
+
properties: {
|
|
9823
|
+
action: {
|
|
9824
|
+
type: "string",
|
|
9825
|
+
enum: ["list_groups", "activate", "deactivate", "set_profile"],
|
|
9826
|
+
description: "list_groups: show every group, its tools, and active state; activate/deactivate: toggle one group; set_profile: switch wholesale."
|
|
9827
|
+
},
|
|
9828
|
+
group: { type: "string", enum: [...TOOL_GROUPS], description: "Group for activate/deactivate." },
|
|
9829
|
+
profile: { type: "string", enum: ["core", "full"], description: "Profile for set_profile (core=lean, full=all groups)." }
|
|
9830
|
+
},
|
|
9831
|
+
required: ["action"],
|
|
9832
|
+
additionalProperties: false
|
|
9833
|
+
}
|
|
9834
|
+
},
|
|
9835
|
+
{
|
|
9836
|
+
name: "describe_tool",
|
|
9837
|
+
description: "Return the full description and per-parameter docs for any cdp-toolkit tool by name — including tools not currently listed. Call this before using an unfamiliar tool; the live tools/list carries only terse summaries.",
|
|
9838
|
+
inputSchema: {
|
|
9839
|
+
type: "object",
|
|
9840
|
+
properties: { name: { type: "string", description: "Tool name, e.g. take_screenshot." } },
|
|
9841
|
+
required: ["name"],
|
|
9842
|
+
additionalProperties: false
|
|
9843
|
+
}
|
|
9844
|
+
}
|
|
9845
|
+
];
|
|
9846
|
+
function renderGroups() {
|
|
9847
|
+
const lines = [`profile start=${START_PROFILE}; active groups: ${[...activeGroups].join(", ") || "(none)"}`];
|
|
9848
|
+
for (const g of TOOL_GROUPS) {
|
|
9849
|
+
const shown = GROUP_TOOLS[g].filter((n) => AVAILABLE_NAMES.has(n));
|
|
9850
|
+
lines.push(`${activeGroups.has(g) ? "[on] " : "[off]"} ${g} (${shown.length}): ${shown.join(", ")}`);
|
|
9851
|
+
}
|
|
9852
|
+
return lines.join(`
|
|
9853
|
+
`);
|
|
9854
|
+
}
|
|
9855
|
+
function renderToolDoc(toolName) {
|
|
9856
|
+
const doc = TOOL_DOCS[toolName];
|
|
9857
|
+
if (!doc)
|
|
9858
|
+
return `unknown tool: ${toolName}`;
|
|
9859
|
+
const group = TOOL_GROUP[toolName];
|
|
9860
|
+
const params = Object.entries(doc.params);
|
|
9861
|
+
const body = params.length ? params.map(([p, d]) => `- ${p}: ${d || "(no description)"}`).join(`
|
|
9862
|
+
`) : "(no parameters)";
|
|
9863
|
+
return `${toolName}${group ? ` [group: ${group}]` : ""}
|
|
9864
|
+
|
|
9865
|
+
${doc.description}
|
|
9866
|
+
|
|
9867
|
+
Parameters:
|
|
9868
|
+
${body}`;
|
|
9869
|
+
}
|
|
9870
|
+
var server = new Server({ name: "cdp-toolkit", version: VERSION }, { capabilities: { tools: { listChanged: true } }, instructions: INSTRUCTIONS });
|
|
9871
|
+
server.setRequestHandler("tools/list", async () => ({
|
|
9872
|
+
tools: [
|
|
9873
|
+
...META_TOOLS,
|
|
9874
|
+
...MANIFEST.filter((s) => AVAILABLE_NAMES.has(s.name) && activeGroups.has(TOOL_GROUP[s.name] ?? "")).map((s) => ({ name: s.name, description: s.description, inputSchema: s.inputSchema }))
|
|
9875
|
+
]
|
|
8922
9876
|
}));
|
|
8923
|
-
server.setRequestHandler(
|
|
9877
|
+
server.setRequestHandler("tools/call", async (request) => {
|
|
8924
9878
|
const { name } = request.params;
|
|
8925
9879
|
const args = request.params.arguments ?? {};
|
|
9880
|
+
if (name === "describe_tool") {
|
|
9881
|
+
const toolName = typeof args.name === "string" ? args.name : "";
|
|
9882
|
+
const known = Boolean(TOOL_DOCS[toolName]);
|
|
9883
|
+
return { content: [{ type: "text", text: renderToolDoc(toolName) }], isError: !known };
|
|
9884
|
+
}
|
|
9885
|
+
if (name === "browser_tools") {
|
|
9886
|
+
const a = args;
|
|
9887
|
+
const action = typeof a.action === "string" ? a.action : "";
|
|
9888
|
+
const before = [...activeGroups].sort().join(",");
|
|
9889
|
+
if (action === "list_groups") {
|
|
9890
|
+
return { content: [{ type: "text", text: renderGroups() }] };
|
|
9891
|
+
}
|
|
9892
|
+
if (action === "activate" || action === "deactivate") {
|
|
9893
|
+
const group = typeof a.group === "string" ? a.group : "";
|
|
9894
|
+
if (!TOOL_GROUPS.includes(group)) {
|
|
9895
|
+
return { content: [{ type: "text", text: `unknown group: ${group}. Known: ${TOOL_GROUPS.join(", ")}` }], isError: true };
|
|
9896
|
+
}
|
|
9897
|
+
if (action === "activate")
|
|
9898
|
+
activeGroups.add(group);
|
|
9899
|
+
else
|
|
9900
|
+
activeGroups.delete(group);
|
|
9901
|
+
} else if (action === "set_profile") {
|
|
9902
|
+
const profile = a.profile === "full" ? "full" : a.profile === "core" ? "core" : "";
|
|
9903
|
+
if (!profile)
|
|
9904
|
+
return { content: [{ type: "text", text: `unknown profile: ${String(a.profile)}. Known: core, full` }], isError: true };
|
|
9905
|
+
activeGroups.clear();
|
|
9906
|
+
for (const g of PROFILES[profile])
|
|
9907
|
+
activeGroups.add(g);
|
|
9908
|
+
} else {
|
|
9909
|
+
return { content: [{ type: "text", text: `unknown action: ${action}. Use list_groups | activate | deactivate | set_profile.` }], isError: true };
|
|
9910
|
+
}
|
|
9911
|
+
if ([...activeGroups].sort().join(",") !== before) {
|
|
9912
|
+
try {
|
|
9913
|
+
await server.sendToolListChanged();
|
|
9914
|
+
} catch (err) {
|
|
9915
|
+
console.error(`[cdp-toolkit] WARN: sendToolListChanged failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
9916
|
+
}
|
|
9917
|
+
}
|
|
9918
|
+
return { content: [{ type: "text", text: renderGroups() }] };
|
|
9919
|
+
}
|
|
8926
9920
|
if (!AVAILABLE_NAMES.has(name)) {
|
|
8927
9921
|
const gap = AVAILABILITY.unavailable.find((u) => u.name === name);
|
|
8928
9922
|
return {
|