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/cli.js
CHANGED
|
@@ -5396,6 +5396,252 @@ async function connectBidiSessionUrl(wsUrl, opts = {}) {
|
|
|
5396
5396
|
return conn;
|
|
5397
5397
|
}
|
|
5398
5398
|
|
|
5399
|
+
// src/bidi/session-lease.ts
|
|
5400
|
+
import { mkdir as mkdir12, readFile as readFile8, unlink as unlink5, writeFile as writeFile9 } from "node:fs/promises";
|
|
5401
|
+
import { join as join10 } from "node:path";
|
|
5402
|
+
var DEFAULT_SESSION_WAIT_MS = 1e4;
|
|
5403
|
+
var DEFAULT_POLL_MS = 250;
|
|
5404
|
+
function safeEndpoint(endpoint) {
|
|
5405
|
+
return endpoint.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
5406
|
+
}
|
|
5407
|
+
function sessionSlotFile(endpoint) {
|
|
5408
|
+
return join10(leaseDir(), `ff-session-${safeEndpoint(endpoint)}.json`);
|
|
5409
|
+
}
|
|
5410
|
+
function sessionWaitMs() {
|
|
5411
|
+
const raw = Number(process.env.CDP_FIREFOX_SESSION_WAIT_MS);
|
|
5412
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_SESSION_WAIT_MS;
|
|
5413
|
+
}
|
|
5414
|
+
|
|
5415
|
+
class SessionSlotBusyError extends Error {
|
|
5416
|
+
endpoint;
|
|
5417
|
+
holderPid;
|
|
5418
|
+
holderLabel;
|
|
5419
|
+
constructor(endpoint, holder) {
|
|
5420
|
+
const who = holder ? `'${holder.label}' (pid ${holder.pid})` : "another live process";
|
|
5421
|
+
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.`);
|
|
5422
|
+
this.name = "SessionSlotBusyError";
|
|
5423
|
+
this.endpoint = endpoint;
|
|
5424
|
+
if (holder) {
|
|
5425
|
+
this.holderPid = holder.pid;
|
|
5426
|
+
this.holderLabel = holder.label;
|
|
5427
|
+
}
|
|
5428
|
+
}
|
|
5429
|
+
}
|
|
5430
|
+
async function readSessionSlot(endpoint) {
|
|
5431
|
+
let raw;
|
|
5432
|
+
try {
|
|
5433
|
+
raw = await readFile8(sessionSlotFile(endpoint), "utf8");
|
|
5434
|
+
} catch (err) {
|
|
5435
|
+
if (err.code === "ENOENT")
|
|
5436
|
+
return;
|
|
5437
|
+
throw err;
|
|
5438
|
+
}
|
|
5439
|
+
try {
|
|
5440
|
+
const rec = JSON.parse(raw);
|
|
5441
|
+
if (typeof rec?.pid === "number" && typeof rec?.endpoint === "string" && typeof rec?.label === "string") {
|
|
5442
|
+
return rec;
|
|
5443
|
+
}
|
|
5444
|
+
} catch {}
|
|
5445
|
+
return;
|
|
5446
|
+
}
|
|
5447
|
+
async function acquireSessionSlot(endpoint, opts) {
|
|
5448
|
+
const waitMs = opts.waitMs ?? sessionWaitMs();
|
|
5449
|
+
const pollMs = opts.pollMs !== undefined && opts.pollMs > 0 ? opts.pollMs : DEFAULT_POLL_MS;
|
|
5450
|
+
const createdAt = opts.now ?? Date.now();
|
|
5451
|
+
const file = sessionSlotFile(endpoint);
|
|
5452
|
+
const record2 = {
|
|
5453
|
+
endpoint,
|
|
5454
|
+
pid: process.pid,
|
|
5455
|
+
label: opts.label,
|
|
5456
|
+
createdAt
|
|
5457
|
+
};
|
|
5458
|
+
if (opts.marionettePort !== undefined)
|
|
5459
|
+
record2.marionettePort = opts.marionettePort;
|
|
5460
|
+
const handle = { endpoint, pid: process.pid, createdAt };
|
|
5461
|
+
const payload = JSON.stringify(record2);
|
|
5462
|
+
await mkdir12(leaseDir(), { recursive: true });
|
|
5463
|
+
const deadline = Date.now() + waitMs;
|
|
5464
|
+
const maxAttempts = Math.max(100, Math.ceil(waitMs / pollMs) + 100);
|
|
5465
|
+
let attempts = 0;
|
|
5466
|
+
let lastLiveHolder;
|
|
5467
|
+
while (true) {
|
|
5468
|
+
if (attempts >= maxAttempts)
|
|
5469
|
+
throw new SessionSlotBusyError(endpoint, lastLiveHolder);
|
|
5470
|
+
attempts++;
|
|
5471
|
+
try {
|
|
5472
|
+
await writeFile9(file, payload, { flag: "wx" });
|
|
5473
|
+
return { handle };
|
|
5474
|
+
} catch (err) {
|
|
5475
|
+
if (err.code !== "EEXIST")
|
|
5476
|
+
throw err;
|
|
5477
|
+
}
|
|
5478
|
+
const holder = await readSessionSlot(endpoint);
|
|
5479
|
+
if (!holder)
|
|
5480
|
+
continue;
|
|
5481
|
+
if (!isPidAlive(holder.pid)) {
|
|
5482
|
+
await unlink5(file).catch(() => {
|
|
5483
|
+
return;
|
|
5484
|
+
});
|
|
5485
|
+
try {
|
|
5486
|
+
await writeFile9(file, payload, { flag: "wx" });
|
|
5487
|
+
return { handle, staleHolder: holder };
|
|
5488
|
+
} catch (err) {
|
|
5489
|
+
if (err.code !== "EEXIST")
|
|
5490
|
+
throw err;
|
|
5491
|
+
continue;
|
|
5492
|
+
}
|
|
5493
|
+
}
|
|
5494
|
+
lastLiveHolder = holder;
|
|
5495
|
+
const remaining = deadline - Date.now();
|
|
5496
|
+
if (remaining <= 0)
|
|
5497
|
+
throw new SessionSlotBusyError(endpoint, holder);
|
|
5498
|
+
await sleep2(Math.min(pollMs, remaining));
|
|
5499
|
+
}
|
|
5500
|
+
}
|
|
5501
|
+
async function releaseSessionSlot(handle) {
|
|
5502
|
+
const current = await readSessionSlot(handle.endpoint);
|
|
5503
|
+
if (!current)
|
|
5504
|
+
return { released: false };
|
|
5505
|
+
if (current.pid !== process.pid || current.createdAt !== handle.createdAt)
|
|
5506
|
+
return { released: false };
|
|
5507
|
+
await unlink5(sessionSlotFile(handle.endpoint)).catch(() => {
|
|
5508
|
+
return;
|
|
5509
|
+
});
|
|
5510
|
+
return { released: true };
|
|
5511
|
+
}
|
|
5512
|
+
function sleep2(ms) {
|
|
5513
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
5514
|
+
}
|
|
5515
|
+
|
|
5516
|
+
// src/bidi/marionette.ts
|
|
5517
|
+
import { Socket } from "node:net";
|
|
5518
|
+
var DEFAULT_MARIONETTE_PORT = 2828;
|
|
5519
|
+
var DEFAULT_TIMEOUT_MS3 = 4000;
|
|
5520
|
+
var HOST = "127.0.0.1";
|
|
5521
|
+
var COLON = 58;
|
|
5522
|
+
var DELETE_SESSION_FRAME = encodeFrame([0, 1, "WebDriver:DeleteSession", {}]);
|
|
5523
|
+
function defaultMarionettePort() {
|
|
5524
|
+
const raw = Number(process.env.CDP_FIREFOX_MARIONETTE_PORT);
|
|
5525
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_MARIONETTE_PORT;
|
|
5526
|
+
}
|
|
5527
|
+
function encodeFrame(json) {
|
|
5528
|
+
const body = Buffer.from(JSON.stringify(json), "utf8");
|
|
5529
|
+
const prefix = Buffer.from(`${body.length}:`, "ascii");
|
|
5530
|
+
return Buffer.concat([prefix, body]);
|
|
5531
|
+
}
|
|
5532
|
+
|
|
5533
|
+
class MarionetteProtocolError extends Error {
|
|
5534
|
+
constructor(message) {
|
|
5535
|
+
super(message);
|
|
5536
|
+
this.name = "MarionetteProtocolError";
|
|
5537
|
+
}
|
|
5538
|
+
}
|
|
5539
|
+
|
|
5540
|
+
class FrameDecoder {
|
|
5541
|
+
buf = Buffer.alloc(0);
|
|
5542
|
+
push(chunk) {
|
|
5543
|
+
this.buf = this.buf.length === 0 ? chunk : Buffer.concat([this.buf, chunk]);
|
|
5544
|
+
}
|
|
5545
|
+
next() {
|
|
5546
|
+
const colon = this.buf.indexOf(COLON);
|
|
5547
|
+
if (colon === -1) {
|
|
5548
|
+
this.assertDigitsPrefix(this.buf.length);
|
|
5549
|
+
return;
|
|
5550
|
+
}
|
|
5551
|
+
if (colon === 0)
|
|
5552
|
+
throw new MarionetteProtocolError("empty frame length prefix");
|
|
5553
|
+
this.assertDigitsPrefix(colon);
|
|
5554
|
+
const len = Number.parseInt(this.buf.toString("ascii", 0, colon), 10);
|
|
5555
|
+
const start = colon + 1;
|
|
5556
|
+
const end = start + len;
|
|
5557
|
+
if (this.buf.length < end)
|
|
5558
|
+
return;
|
|
5559
|
+
const payload = this.buf.toString("utf8", start, end);
|
|
5560
|
+
this.buf = this.buf.subarray(end);
|
|
5561
|
+
try {
|
|
5562
|
+
return JSON.parse(payload);
|
|
5563
|
+
} catch {
|
|
5564
|
+
throw new MarionetteProtocolError(`frame body was not valid JSON (${len} bytes): ${payload.slice(0, 80)}`);
|
|
5565
|
+
}
|
|
5566
|
+
}
|
|
5567
|
+
assertDigitsPrefix(upTo) {
|
|
5568
|
+
for (let i = 0;i < upTo; i++) {
|
|
5569
|
+
const b = this.buf[i];
|
|
5570
|
+
if (b < 48 || b > 57) {
|
|
5571
|
+
throw new MarionetteProtocolError(`non-digit byte 0x${b.toString(16)} in frame length prefix`);
|
|
5572
|
+
}
|
|
5573
|
+
}
|
|
5574
|
+
}
|
|
5575
|
+
}
|
|
5576
|
+
function isSlotFreedReply(frame) {
|
|
5577
|
+
if (!Array.isArray(frame))
|
|
5578
|
+
return false;
|
|
5579
|
+
const err = frame[2];
|
|
5580
|
+
if (err === null)
|
|
5581
|
+
return true;
|
|
5582
|
+
if (typeof err === "object" && err !== null && err.error === "invalid session id") {
|
|
5583
|
+
return true;
|
|
5584
|
+
}
|
|
5585
|
+
return false;
|
|
5586
|
+
}
|
|
5587
|
+
function forceClearOrphanSession(marionettePort, opts = {}) {
|
|
5588
|
+
const timeoutMs = opts.timeoutMs !== undefined && Number.isFinite(opts.timeoutMs) && opts.timeoutMs > 0 ? opts.timeoutMs : DEFAULT_TIMEOUT_MS3;
|
|
5589
|
+
return new Promise((resolve) => {
|
|
5590
|
+
if (!Number.isFinite(marionettePort) || marionettePort <= 0 || marionettePort > 65535) {
|
|
5591
|
+
resolve(false);
|
|
5592
|
+
return;
|
|
5593
|
+
}
|
|
5594
|
+
const sock = new Socket;
|
|
5595
|
+
const decoder = new FrameDecoder;
|
|
5596
|
+
let settled = false;
|
|
5597
|
+
let handshakeSeen = false;
|
|
5598
|
+
let commandSent = false;
|
|
5599
|
+
const settle = (value) => {
|
|
5600
|
+
if (settled)
|
|
5601
|
+
return;
|
|
5602
|
+
settled = true;
|
|
5603
|
+
clearTimeout(timer);
|
|
5604
|
+
sock.removeAllListeners();
|
|
5605
|
+
sock.destroy();
|
|
5606
|
+
resolve(value);
|
|
5607
|
+
};
|
|
5608
|
+
const timer = setTimeout(() => settle(false), timeoutMs);
|
|
5609
|
+
if (typeof timer.unref === "function")
|
|
5610
|
+
timer.unref();
|
|
5611
|
+
sock.on("error", () => settle(false));
|
|
5612
|
+
sock.on("close", () => settle(false));
|
|
5613
|
+
sock.on("data", (chunk) => {
|
|
5614
|
+
if (settled)
|
|
5615
|
+
return;
|
|
5616
|
+
try {
|
|
5617
|
+
decoder.push(chunk);
|
|
5618
|
+
for (;; ) {
|
|
5619
|
+
const frame = decoder.next();
|
|
5620
|
+
if (frame === undefined)
|
|
5621
|
+
break;
|
|
5622
|
+
if (!handshakeSeen) {
|
|
5623
|
+
handshakeSeen = true;
|
|
5624
|
+
continue;
|
|
5625
|
+
}
|
|
5626
|
+
settle(isSlotFreedReply(frame));
|
|
5627
|
+
return;
|
|
5628
|
+
}
|
|
5629
|
+
if (handshakeSeen && !commandSent) {
|
|
5630
|
+
commandSent = true;
|
|
5631
|
+
sock.write(DELETE_SESSION_FRAME);
|
|
5632
|
+
}
|
|
5633
|
+
} catch {
|
|
5634
|
+
settle(false);
|
|
5635
|
+
}
|
|
5636
|
+
});
|
|
5637
|
+
try {
|
|
5638
|
+
sock.connect(marionettePort, HOST);
|
|
5639
|
+
} catch {
|
|
5640
|
+
settle(false);
|
|
5641
|
+
}
|
|
5642
|
+
});
|
|
5643
|
+
}
|
|
5644
|
+
|
|
5399
5645
|
// src/bidi/snapshot.ts
|
|
5400
5646
|
var STAMP_ATTR = "data-cdp-uid";
|
|
5401
5647
|
async function takeStampedSnapshot(evaluate) {
|
|
@@ -5774,6 +6020,9 @@ function mapBidiError(e) {
|
|
|
5774
6020
|
return driverError2("timeout", e.message);
|
|
5775
6021
|
if (!code && /(disposed|not open|connection closed)/i.test(e.message))
|
|
5776
6022
|
return driverError2("disconnected", e.message);
|
|
6023
|
+
if (/NS_ERROR_FILE_ACCESS_DENIED/i.test(e.message)) {
|
|
6024
|
+
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.`);
|
|
6025
|
+
}
|
|
5777
6026
|
return driverError2("page-error", e.message);
|
|
5778
6027
|
}
|
|
5779
6028
|
return driverError2("page-error", e instanceof Error ? e.message : String(e));
|
|
@@ -5972,6 +6221,22 @@ var BIDI_CAPABILITIES = new Set([
|
|
|
5972
6221
|
"locate.xpath"
|
|
5973
6222
|
]);
|
|
5974
6223
|
var connections = new Map;
|
|
6224
|
+
var slotHandles = new Map;
|
|
6225
|
+
var connecting = new Map;
|
|
6226
|
+
async function releaseSlotOnDialFailure(endpoint, owned) {
|
|
6227
|
+
if (owned)
|
|
6228
|
+
return;
|
|
6229
|
+
const h = slotHandles.get(endpoint);
|
|
6230
|
+
if (h) {
|
|
6231
|
+
await releaseSessionSlot(h).catch(() => {
|
|
6232
|
+
return;
|
|
6233
|
+
});
|
|
6234
|
+
slotHandles.delete(endpoint);
|
|
6235
|
+
}
|
|
6236
|
+
}
|
|
6237
|
+
function orphanNotClearedError(endpoint) {
|
|
6238
|
+
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.)`);
|
|
6239
|
+
}
|
|
5975
6240
|
async function getConnection(endpoint, timeoutMs) {
|
|
5976
6241
|
const existing = connections.get(endpoint);
|
|
5977
6242
|
if (existing && existing.isOpen) {
|
|
@@ -5980,17 +6245,68 @@ async function getConnection(endpoint, timeoutMs) {
|
|
|
5980
6245
|
}
|
|
5981
6246
|
if (existing)
|
|
5982
6247
|
connections.delete(endpoint);
|
|
5983
|
-
const
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
6248
|
+
const inflight = connecting.get(endpoint);
|
|
6249
|
+
if (inflight) {
|
|
6250
|
+
const conn = await inflight;
|
|
6251
|
+
conn.retain();
|
|
6252
|
+
return conn;
|
|
6253
|
+
}
|
|
6254
|
+
const create = (async () => {
|
|
6255
|
+
const mport = defaultMarionettePort();
|
|
6256
|
+
const owned = slotHandles.has(endpoint);
|
|
6257
|
+
if (!owned) {
|
|
6258
|
+
let acq;
|
|
6259
|
+
try {
|
|
6260
|
+
acq = await acquireSessionSlot(endpoint, { label: defaultLabel(), marionettePort: mport });
|
|
6261
|
+
} catch (e) {
|
|
6262
|
+
if (e instanceof SessionSlotBusyError) {
|
|
6263
|
+
const who = e.holderLabel ? `'${e.holderLabel}' (pid ${e.holderPid})` : "another live process";
|
|
6264
|
+
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.`);
|
|
6265
|
+
}
|
|
6266
|
+
throw e;
|
|
6267
|
+
}
|
|
6268
|
+
slotHandles.set(endpoint, acq.handle);
|
|
6269
|
+
if (acq.staleHolder) {
|
|
6270
|
+
await forceClearOrphanSession(acq.staleHolder.marionettePort ?? mport);
|
|
6271
|
+
}
|
|
5989
6272
|
}
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
6273
|
+
const dialOpts = {
|
|
6274
|
+
...timeoutMs !== undefined ? { timeoutMs } : {},
|
|
6275
|
+
capabilities: { alwaysMatch: { unhandledPromptBehavior: { default: "ignore" } } }
|
|
6276
|
+
};
|
|
6277
|
+
let conn;
|
|
6278
|
+
try {
|
|
6279
|
+
conn = await connectBidiSessionUrl(endpoint, dialOpts);
|
|
6280
|
+
} catch (e) {
|
|
6281
|
+
if (e instanceof BidiError && /maximum number of active sessions/i.test(e.message)) {
|
|
6282
|
+
const cleared = await forceClearOrphanSession(mport);
|
|
6283
|
+
if (!cleared) {
|
|
6284
|
+
await releaseSlotOnDialFailure(endpoint, owned);
|
|
6285
|
+
throw orphanNotClearedError(endpoint);
|
|
6286
|
+
}
|
|
6287
|
+
try {
|
|
6288
|
+
conn = await connectBidiSessionUrl(endpoint, dialOpts);
|
|
6289
|
+
} catch (e2) {
|
|
6290
|
+
await releaseSlotOnDialFailure(endpoint, owned);
|
|
6291
|
+
if (e2 instanceof BidiError && /maximum number of active sessions/i.test(e2.message)) {
|
|
6292
|
+
throw orphanNotClearedError(endpoint);
|
|
6293
|
+
}
|
|
6294
|
+
throw e2;
|
|
6295
|
+
}
|
|
6296
|
+
} else {
|
|
6297
|
+
await releaseSlotOnDialFailure(endpoint, owned);
|
|
6298
|
+
throw e;
|
|
6299
|
+
}
|
|
6300
|
+
}
|
|
6301
|
+
connections.set(endpoint, conn);
|
|
6302
|
+
return conn;
|
|
6303
|
+
})();
|
|
6304
|
+
connecting.set(endpoint, create);
|
|
6305
|
+
try {
|
|
6306
|
+
return await create;
|
|
6307
|
+
} finally {
|
|
6308
|
+
connecting.delete(endpoint);
|
|
6309
|
+
}
|
|
5994
6310
|
}
|
|
5995
6311
|
var bidiBeaconScripts = new Map;
|
|
5996
6312
|
async function safeTitle(conn, contextId) {
|
|
@@ -6103,7 +6419,10 @@ class BidiPageDriver {
|
|
|
6103
6419
|
const sendOpts = opts.timeoutMs !== undefined ? { timeoutMs: opts.timeoutMs } : {};
|
|
6104
6420
|
try {
|
|
6105
6421
|
if (reload) {
|
|
6106
|
-
|
|
6422
|
+
if (opts.ignoreCache === true) {
|
|
6423
|
+
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.");
|
|
6424
|
+
}
|
|
6425
|
+
const r2 = await this.conn.send("browsingContext.reload", { context: this.contextId, wait }, sendOpts);
|
|
6107
6426
|
return { url: r2.url, contextId: this.contextId, reloaded: true, waitedFor: waitUntil };
|
|
6108
6427
|
}
|
|
6109
6428
|
if (history) {
|
|
@@ -6756,14 +7075,27 @@ class BidiBrowserDriver {
|
|
|
6756
7075
|
if (key.startsWith(`${this.endpoint}:`))
|
|
6757
7076
|
bidiBeaconScripts.delete(key);
|
|
6758
7077
|
}
|
|
7078
|
+
connecting.delete(this.endpoint);
|
|
6759
7079
|
const conn = connections.get(this.endpoint);
|
|
6760
|
-
if (!conn)
|
|
7080
|
+
if (!conn) {
|
|
7081
|
+
await this.releaseSessionSlotIfHeld();
|
|
6761
7082
|
return;
|
|
7083
|
+
}
|
|
6762
7084
|
connections.delete(this.endpoint);
|
|
6763
7085
|
await conn.send("session.end", {}).catch(() => {
|
|
6764
7086
|
return;
|
|
6765
7087
|
});
|
|
6766
7088
|
conn.dispose();
|
|
7089
|
+
await this.releaseSessionSlotIfHeld();
|
|
7090
|
+
}
|
|
7091
|
+
async releaseSessionSlotIfHeld() {
|
|
7092
|
+
const h = slotHandles.get(this.endpoint);
|
|
7093
|
+
if (!h)
|
|
7094
|
+
return;
|
|
7095
|
+
await releaseSessionSlot(h).catch(() => {
|
|
7096
|
+
return;
|
|
7097
|
+
});
|
|
7098
|
+
slotHandles.delete(this.endpoint);
|
|
6767
7099
|
}
|
|
6768
7100
|
}
|
|
6769
7101
|
function createFirefoxDriver(port, opts) {
|
|
@@ -6775,10 +7107,10 @@ function createFirefoxDriverForEndpoint(wsUrl, opts) {
|
|
|
6775
7107
|
|
|
6776
7108
|
// src/bidi/launch.ts
|
|
6777
7109
|
import { spawn as spawn3 } from "node:child_process";
|
|
6778
|
-
import { existsSync, mkdtempSync, rmSync } from "node:fs";
|
|
7110
|
+
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
6779
7111
|
import { createConnection, createServer } from "node:net";
|
|
6780
7112
|
import { tmpdir } from "node:os";
|
|
6781
|
-
import { join as
|
|
7113
|
+
import { join as join11 } from "node:path";
|
|
6782
7114
|
function resolveBinary() {
|
|
6783
7115
|
const candidates = [
|
|
6784
7116
|
process.env.FIREFOX_BIN,
|
|
@@ -6852,11 +7184,37 @@ function waitForExit(proc, deadlineMs) {
|
|
|
6852
7184
|
});
|
|
6853
7185
|
});
|
|
6854
7186
|
}
|
|
7187
|
+
var LAUNCH_USER_JS_PREFS = {
|
|
7188
|
+
"remote.prefs.recommended": true,
|
|
7189
|
+
"security.fileuri.strict_origin_policy": false,
|
|
7190
|
+
"dom.file.createInChild": true
|
|
7191
|
+
};
|
|
7192
|
+
function writeLaunchUserJs(profilePath) {
|
|
7193
|
+
const target = join11(profilePath, "user.js");
|
|
7194
|
+
const existing = existsSync(target) ? readFileSync(target, "utf8") : "";
|
|
7195
|
+
const present = new Set;
|
|
7196
|
+
for (const line of existing.split(`
|
|
7197
|
+
`)) {
|
|
7198
|
+
const m = /^user_pref\("([^"]+)"\s*,/.exec(line.trim());
|
|
7199
|
+
if (m)
|
|
7200
|
+
present.add(m[1]);
|
|
7201
|
+
}
|
|
7202
|
+
const additions = Object.entries(LAUNCH_USER_JS_PREFS).filter(([k]) => !present.has(k)).map(([k, v]) => `user_pref("${k}", ${JSON.stringify(v)});`);
|
|
7203
|
+
const content = (existing.length > 0 ? existing.replace(/\n*$/, `
|
|
7204
|
+
`) : "") + additions.join(`
|
|
7205
|
+
`) + (additions.length > 0 ? `
|
|
7206
|
+
` : "");
|
|
7207
|
+
if (content !== existing)
|
|
7208
|
+
writeFileSync(target, content, "utf-8");
|
|
7209
|
+
return content;
|
|
7210
|
+
}
|
|
6855
7211
|
async function launchFirefox(opts = {}) {
|
|
6856
7212
|
const binary = resolveBinary();
|
|
6857
7213
|
const port = await pickPort(opts.port);
|
|
6858
7214
|
const isThrowaway = opts.profilePath === undefined;
|
|
6859
|
-
const profilePath = opts.profilePath ?? mkdtempSync(
|
|
7215
|
+
const profilePath = opts.profilePath ?? mkdtempSync(join11(tmpdir(), "cdp-toolkit-ff-profile-"));
|
|
7216
|
+
if (isThrowaway)
|
|
7217
|
+
writeLaunchUserJs(profilePath);
|
|
6860
7218
|
const args = ["--profile", profilePath, "--remote-debugging-port", String(port), "--no-remote"];
|
|
6861
7219
|
if (opts.headless)
|
|
6862
7220
|
args.push("--headless");
|
|
@@ -7210,21 +7568,21 @@ var FIREFOX_TOOLS = {
|
|
|
7210
7568
|
var MANIFEST = [
|
|
7211
7569
|
{
|
|
7212
7570
|
name: "list_pages",
|
|
7213
|
-
description: "
|
|
7571
|
+
description: "List browser page targets; optionally include non-page targets and probe responsiveness.",
|
|
7214
7572
|
inputSchema: {
|
|
7215
7573
|
type: "object",
|
|
7216
7574
|
properties: {
|
|
7217
7575
|
lease: {
|
|
7218
7576
|
type: "string",
|
|
7219
|
-
description: "Lease token
|
|
7577
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7220
7578
|
},
|
|
7221
7579
|
all: {
|
|
7222
7580
|
type: "boolean",
|
|
7223
|
-
description: "Include non-page targets
|
|
7581
|
+
description: "Include non-page targets."
|
|
7224
7582
|
},
|
|
7225
7583
|
probe: {
|
|
7226
7584
|
type: "boolean",
|
|
7227
|
-
description: "
|
|
7585
|
+
description: "Probe renderer responsiveness."
|
|
7228
7586
|
}
|
|
7229
7587
|
},
|
|
7230
7588
|
required: [],
|
|
@@ -7233,29 +7591,29 @@ var MANIFEST = [
|
|
|
7233
7591
|
},
|
|
7234
7592
|
{
|
|
7235
7593
|
name: "new_page",
|
|
7236
|
-
description: "Open a
|
|
7594
|
+
description: "Open a browser tab, optionally claim it; navigation is not awaited.",
|
|
7237
7595
|
inputSchema: {
|
|
7238
7596
|
type: "object",
|
|
7239
7597
|
properties: {
|
|
7240
7598
|
lease: {
|
|
7241
7599
|
type: "string",
|
|
7242
|
-
description: "Lease token
|
|
7600
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7243
7601
|
},
|
|
7244
7602
|
url: {
|
|
7245
7603
|
type: "string",
|
|
7246
|
-
description: "URL
|
|
7604
|
+
description: "URL value."
|
|
7247
7605
|
},
|
|
7248
7606
|
claim: {
|
|
7249
7607
|
type: "boolean",
|
|
7250
|
-
description: "Claim the new tab
|
|
7608
|
+
description: "Claim the new tab."
|
|
7251
7609
|
},
|
|
7252
7610
|
label: {
|
|
7253
7611
|
type: "string",
|
|
7254
|
-
description: "Agent
|
|
7612
|
+
description: "Agent lease label."
|
|
7255
7613
|
},
|
|
7256
7614
|
ttlMs: {
|
|
7257
7615
|
type: "number",
|
|
7258
|
-
description: "
|
|
7616
|
+
description: "Lease TTL in milliseconds."
|
|
7259
7617
|
}
|
|
7260
7618
|
},
|
|
7261
7619
|
required: [],
|
|
@@ -7264,17 +7622,17 @@ var MANIFEST = [
|
|
|
7264
7622
|
},
|
|
7265
7623
|
{
|
|
7266
7624
|
name: "close_page",
|
|
7267
|
-
description: "Close a page target
|
|
7625
|
+
description: "Close a selected page; target must resolve explicitly.",
|
|
7268
7626
|
inputSchema: {
|
|
7269
7627
|
type: "object",
|
|
7270
7628
|
properties: {
|
|
7271
7629
|
lease: {
|
|
7272
7630
|
type: "string",
|
|
7273
|
-
description: "Lease token
|
|
7631
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7274
7632
|
},
|
|
7275
7633
|
target: {
|
|
7276
7634
|
type: "string",
|
|
7277
|
-
description: "Page selector
|
|
7635
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7278
7636
|
}
|
|
7279
7637
|
},
|
|
7280
7638
|
required: [
|
|
@@ -7285,17 +7643,17 @@ var MANIFEST = [
|
|
|
7285
7643
|
},
|
|
7286
7644
|
{
|
|
7287
7645
|
name: "select_page",
|
|
7288
|
-
description: "
|
|
7646
|
+
description: "Focus a selected page and persist it as active; target must resolve explicitly.",
|
|
7289
7647
|
inputSchema: {
|
|
7290
7648
|
type: "object",
|
|
7291
7649
|
properties: {
|
|
7292
7650
|
lease: {
|
|
7293
7651
|
type: "string",
|
|
7294
|
-
description: "Lease token
|
|
7652
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7295
7653
|
},
|
|
7296
7654
|
target: {
|
|
7297
7655
|
type: "string",
|
|
7298
|
-
description: "Page selector
|
|
7656
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7299
7657
|
}
|
|
7300
7658
|
},
|
|
7301
7659
|
required: [
|
|
@@ -7306,25 +7664,25 @@ var MANIFEST = [
|
|
|
7306
7664
|
},
|
|
7307
7665
|
{
|
|
7308
7666
|
name: "navigate_page",
|
|
7309
|
-
description: "Navigate
|
|
7667
|
+
description: "Navigate, reload, or traverse page history; choose exactly one operation.",
|
|
7310
7668
|
inputSchema: {
|
|
7311
7669
|
type: "object",
|
|
7312
7670
|
properties: {
|
|
7313
7671
|
lease: {
|
|
7314
7672
|
type: "string",
|
|
7315
|
-
description: "Lease token
|
|
7673
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7316
7674
|
},
|
|
7317
7675
|
target: {
|
|
7318
7676
|
type: "string",
|
|
7319
|
-
description: "Page selector
|
|
7677
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7320
7678
|
},
|
|
7321
7679
|
url: {
|
|
7322
7680
|
type: "string",
|
|
7323
|
-
description: "
|
|
7681
|
+
description: "URL value."
|
|
7324
7682
|
},
|
|
7325
7683
|
reload: {
|
|
7326
7684
|
type: "boolean",
|
|
7327
|
-
description: "Reload
|
|
7685
|
+
description: "Reload before capture."
|
|
7328
7686
|
},
|
|
7329
7687
|
history: {
|
|
7330
7688
|
type: "string",
|
|
@@ -7332,11 +7690,11 @@ var MANIFEST = [
|
|
|
7332
7690
|
"back",
|
|
7333
7691
|
"forward"
|
|
7334
7692
|
],
|
|
7335
|
-
description: "
|
|
7693
|
+
description: "History direction."
|
|
7336
7694
|
},
|
|
7337
7695
|
ignoreCache: {
|
|
7338
7696
|
type: "boolean",
|
|
7339
|
-
description: "
|
|
7697
|
+
description: "Bypass cache on reload."
|
|
7340
7698
|
},
|
|
7341
7699
|
waitUntil: {
|
|
7342
7700
|
type: "string",
|
|
@@ -7344,11 +7702,11 @@ var MANIFEST = [
|
|
|
7344
7702
|
"load",
|
|
7345
7703
|
"domcontentloaded"
|
|
7346
7704
|
],
|
|
7347
|
-
description: "
|
|
7705
|
+
description: "Load milestone."
|
|
7348
7706
|
},
|
|
7349
7707
|
timeoutMs: {
|
|
7350
7708
|
type: "number",
|
|
7351
|
-
description: "
|
|
7709
|
+
description: "Timeout in milliseconds."
|
|
7352
7710
|
}
|
|
7353
7711
|
},
|
|
7354
7712
|
additionalProperties: false
|
|
@@ -7356,29 +7714,29 @@ var MANIFEST = [
|
|
|
7356
7714
|
},
|
|
7357
7715
|
{
|
|
7358
7716
|
name: "wait_for",
|
|
7359
|
-
description: "
|
|
7717
|
+
description: "Wait for a text substring in document.body.innerText; timeout throws.",
|
|
7360
7718
|
inputSchema: {
|
|
7361
7719
|
type: "object",
|
|
7362
7720
|
properties: {
|
|
7363
7721
|
lease: {
|
|
7364
7722
|
type: "string",
|
|
7365
|
-
description: "Lease token
|
|
7723
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7366
7724
|
},
|
|
7367
7725
|
target: {
|
|
7368
7726
|
type: "string",
|
|
7369
|
-
description: "Page selector
|
|
7727
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7370
7728
|
},
|
|
7371
7729
|
text: {
|
|
7372
7730
|
type: "string",
|
|
7373
|
-
description: "
|
|
7731
|
+
description: "Text substring."
|
|
7374
7732
|
},
|
|
7375
7733
|
timeoutMs: {
|
|
7376
7734
|
type: "number",
|
|
7377
|
-
description: "
|
|
7735
|
+
description: "Timeout in milliseconds."
|
|
7378
7736
|
},
|
|
7379
7737
|
pollMs: {
|
|
7380
7738
|
type: "number",
|
|
7381
|
-
description: "
|
|
7739
|
+
description: "Polling interval in milliseconds."
|
|
7382
7740
|
}
|
|
7383
7741
|
},
|
|
7384
7742
|
required: [
|
|
@@ -7389,37 +7747,37 @@ var MANIFEST = [
|
|
|
7389
7747
|
},
|
|
7390
7748
|
{
|
|
7391
7749
|
name: "evaluate_script",
|
|
7392
|
-
description: "
|
|
7750
|
+
description: "Evaluate JavaScript in a page or Chrome worker; args require a function literal.",
|
|
7393
7751
|
inputSchema: {
|
|
7394
7752
|
type: "object",
|
|
7395
7753
|
properties: {
|
|
7396
7754
|
lease: {
|
|
7397
7755
|
type: "string",
|
|
7398
|
-
description: "Lease token
|
|
7756
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7399
7757
|
},
|
|
7400
7758
|
target: {
|
|
7401
7759
|
type: "string",
|
|
7402
|
-
description: "Page selector
|
|
7760
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7403
7761
|
},
|
|
7404
7762
|
wake: {
|
|
7405
7763
|
type: "boolean",
|
|
7406
|
-
description: "
|
|
7764
|
+
description: "Wake worker before capture."
|
|
7407
7765
|
},
|
|
7408
7766
|
expression: {
|
|
7409
7767
|
type: "string",
|
|
7410
|
-
description: "JavaScript
|
|
7768
|
+
description: "JavaScript expression or function."
|
|
7411
7769
|
},
|
|
7412
7770
|
awaitPromise: {
|
|
7413
7771
|
type: "boolean",
|
|
7414
|
-
description: "Await
|
|
7772
|
+
description: "Await Promise results."
|
|
7415
7773
|
},
|
|
7416
7774
|
args: {
|
|
7417
7775
|
type: "array",
|
|
7418
|
-
description: "Positional JSON
|
|
7776
|
+
description: "Positional JSON arguments."
|
|
7419
7777
|
},
|
|
7420
7778
|
savePath: {
|
|
7421
7779
|
type: "string",
|
|
7422
|
-
description: "
|
|
7780
|
+
description: "Output file path."
|
|
7423
7781
|
}
|
|
7424
7782
|
},
|
|
7425
7783
|
required: [
|
|
@@ -7430,29 +7788,29 @@ var MANIFEST = [
|
|
|
7430
7788
|
},
|
|
7431
7789
|
{
|
|
7432
7790
|
name: "list_cookies",
|
|
7433
|
-
description: "Read
|
|
7791
|
+
description: "Read cookies for a selected page, including httpOnly values; savePath keeps values out of the response.",
|
|
7434
7792
|
inputSchema: {
|
|
7435
7793
|
type: "object",
|
|
7436
7794
|
properties: {
|
|
7437
7795
|
lease: {
|
|
7438
7796
|
type: "string",
|
|
7439
|
-
description: "Lease token
|
|
7797
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7440
7798
|
},
|
|
7441
7799
|
target: {
|
|
7442
7800
|
type: "string",
|
|
7443
|
-
description: "Page selector
|
|
7801
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7444
7802
|
},
|
|
7445
7803
|
domain: {
|
|
7446
7804
|
type: "string",
|
|
7447
|
-
description: "
|
|
7805
|
+
description: "Cookie domain."
|
|
7448
7806
|
},
|
|
7449
7807
|
name: {
|
|
7450
7808
|
type: "string",
|
|
7451
|
-
description: "
|
|
7809
|
+
description: "Cookie name."
|
|
7452
7810
|
},
|
|
7453
7811
|
savePath: {
|
|
7454
7812
|
type: "string",
|
|
7455
|
-
description: "
|
|
7813
|
+
description: "Output file path."
|
|
7456
7814
|
}
|
|
7457
7815
|
},
|
|
7458
7816
|
required: [],
|
|
@@ -7461,49 +7819,49 @@ var MANIFEST = [
|
|
|
7461
7819
|
},
|
|
7462
7820
|
{
|
|
7463
7821
|
name: "set_cookie",
|
|
7464
|
-
description: "
|
|
7822
|
+
description: "Set one page cookie, including httpOnly or secure flags; provide url or domain.",
|
|
7465
7823
|
inputSchema: {
|
|
7466
7824
|
type: "object",
|
|
7467
7825
|
properties: {
|
|
7468
7826
|
lease: {
|
|
7469
7827
|
type: "string",
|
|
7470
|
-
description: "Lease token
|
|
7828
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7471
7829
|
},
|
|
7472
7830
|
target: {
|
|
7473
7831
|
type: "string",
|
|
7474
|
-
description: "Page selector
|
|
7832
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7475
7833
|
},
|
|
7476
7834
|
name: {
|
|
7477
7835
|
type: "string",
|
|
7478
|
-
description: "Cookie name.
|
|
7836
|
+
description: "Cookie name."
|
|
7479
7837
|
},
|
|
7480
7838
|
value: {
|
|
7481
7839
|
type: "string",
|
|
7482
|
-
description: "Cookie value.
|
|
7840
|
+
description: "Cookie value."
|
|
7483
7841
|
},
|
|
7484
7842
|
url: {
|
|
7485
7843
|
type: "string",
|
|
7486
|
-
description: "URL
|
|
7844
|
+
description: "URL value."
|
|
7487
7845
|
},
|
|
7488
7846
|
domain: {
|
|
7489
7847
|
type: "string",
|
|
7490
|
-
description: "Cookie domain
|
|
7848
|
+
description: "Cookie domain."
|
|
7491
7849
|
},
|
|
7492
7850
|
path: {
|
|
7493
7851
|
type: "string",
|
|
7494
|
-
description: "Cookie path
|
|
7852
|
+
description: "Cookie path."
|
|
7495
7853
|
},
|
|
7496
7854
|
expires: {
|
|
7497
7855
|
type: "number",
|
|
7498
|
-
description: "Expiry
|
|
7856
|
+
description: "Expiry Unix time in seconds."
|
|
7499
7857
|
},
|
|
7500
7858
|
httpOnly: {
|
|
7501
7859
|
type: "boolean",
|
|
7502
|
-
description: "Set
|
|
7860
|
+
description: "Set HttpOnly flag."
|
|
7503
7861
|
},
|
|
7504
7862
|
secure: {
|
|
7505
7863
|
type: "boolean",
|
|
7506
|
-
description: "Set
|
|
7864
|
+
description: "Set Secure flag."
|
|
7507
7865
|
},
|
|
7508
7866
|
sameSite: {
|
|
7509
7867
|
type: "string",
|
|
@@ -7513,7 +7871,7 @@ var MANIFEST = [
|
|
|
7513
7871
|
"none",
|
|
7514
7872
|
"default"
|
|
7515
7873
|
],
|
|
7516
|
-
description: "SameSite attribute
|
|
7874
|
+
description: "SameSite attribute."
|
|
7517
7875
|
}
|
|
7518
7876
|
},
|
|
7519
7877
|
required: [
|
|
@@ -7525,33 +7883,33 @@ var MANIFEST = [
|
|
|
7525
7883
|
},
|
|
7526
7884
|
{
|
|
7527
7885
|
name: "delete_cookies",
|
|
7528
|
-
description: "Delete
|
|
7886
|
+
description: "Delete a named page cookie; provide name and url or domain.",
|
|
7529
7887
|
inputSchema: {
|
|
7530
7888
|
type: "object",
|
|
7531
7889
|
properties: {
|
|
7532
7890
|
lease: {
|
|
7533
7891
|
type: "string",
|
|
7534
|
-
description: "Lease token
|
|
7892
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7535
7893
|
},
|
|
7536
7894
|
target: {
|
|
7537
7895
|
type: "string",
|
|
7538
|
-
description: "Page selector
|
|
7896
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7539
7897
|
},
|
|
7540
7898
|
name: {
|
|
7541
7899
|
type: "string",
|
|
7542
|
-
description: "
|
|
7900
|
+
description: "Cookie name."
|
|
7543
7901
|
},
|
|
7544
7902
|
url: {
|
|
7545
7903
|
type: "string",
|
|
7546
|
-
description: "
|
|
7904
|
+
description: "URL value."
|
|
7547
7905
|
},
|
|
7548
7906
|
domain: {
|
|
7549
7907
|
type: "string",
|
|
7550
|
-
description: "
|
|
7908
|
+
description: "Cookie domain."
|
|
7551
7909
|
},
|
|
7552
7910
|
path: {
|
|
7553
7911
|
type: "string",
|
|
7554
|
-
description: "
|
|
7912
|
+
description: "Cookie path."
|
|
7555
7913
|
}
|
|
7556
7914
|
},
|
|
7557
7915
|
required: [
|
|
@@ -7562,21 +7920,21 @@ var MANIFEST = [
|
|
|
7562
7920
|
},
|
|
7563
7921
|
{
|
|
7564
7922
|
name: "take_snapshot",
|
|
7565
|
-
description: "
|
|
7923
|
+
description: "Capture the page accessibility tree with interaction UIDs.",
|
|
7566
7924
|
inputSchema: {
|
|
7567
7925
|
type: "object",
|
|
7568
7926
|
properties: {
|
|
7569
7927
|
lease: {
|
|
7570
7928
|
type: "string",
|
|
7571
|
-
description: "Lease token
|
|
7929
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7572
7930
|
},
|
|
7573
7931
|
target: {
|
|
7574
7932
|
type: "string",
|
|
7575
|
-
description: "Page selector
|
|
7933
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7576
7934
|
},
|
|
7577
7935
|
interactiveOnly: {
|
|
7578
7936
|
type: "boolean",
|
|
7579
|
-
description: "
|
|
7937
|
+
description: "Only interactive nodes."
|
|
7580
7938
|
}
|
|
7581
7939
|
},
|
|
7582
7940
|
required: [],
|
|
@@ -7585,25 +7943,25 @@ var MANIFEST = [
|
|
|
7585
7943
|
},
|
|
7586
7944
|
{
|
|
7587
7945
|
name: "click",
|
|
7588
|
-
description: "Click an element
|
|
7946
|
+
description: "Click an element by UID or CSS selector; provide exactly one.",
|
|
7589
7947
|
inputSchema: {
|
|
7590
7948
|
type: "object",
|
|
7591
7949
|
properties: {
|
|
7592
7950
|
lease: {
|
|
7593
7951
|
type: "string",
|
|
7594
|
-
description: "Lease token
|
|
7952
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7595
7953
|
},
|
|
7596
7954
|
target: {
|
|
7597
7955
|
type: "string",
|
|
7598
|
-
description: "Page selector
|
|
7956
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7599
7957
|
},
|
|
7600
7958
|
uid: {
|
|
7601
7959
|
type: "number",
|
|
7602
|
-
description: "
|
|
7960
|
+
description: "Element backendDOMNodeId."
|
|
7603
7961
|
},
|
|
7604
7962
|
selector: {
|
|
7605
7963
|
type: "string",
|
|
7606
|
-
description: "CSS selector
|
|
7964
|
+
description: "CSS selector."
|
|
7607
7965
|
},
|
|
7608
7966
|
button: {
|
|
7609
7967
|
type: "string",
|
|
@@ -7612,11 +7970,11 @@ var MANIFEST = [
|
|
|
7612
7970
|
"right",
|
|
7613
7971
|
"middle"
|
|
7614
7972
|
],
|
|
7615
|
-
description: "Mouse button
|
|
7973
|
+
description: "Mouse button."
|
|
7616
7974
|
},
|
|
7617
7975
|
clickCount: {
|
|
7618
7976
|
type: "number",
|
|
7619
|
-
description: "
|
|
7977
|
+
description: "Click count."
|
|
7620
7978
|
},
|
|
7621
7979
|
modifiers: {
|
|
7622
7980
|
type: "array",
|
|
@@ -7629,7 +7987,7 @@ var MANIFEST = [
|
|
|
7629
7987
|
"Shift"
|
|
7630
7988
|
]
|
|
7631
7989
|
},
|
|
7632
|
-
description: "Modifier keys
|
|
7990
|
+
description: "Modifier keys: Control|Ctrl|Shift|Alt|Meta|Cmd."
|
|
7633
7991
|
}
|
|
7634
7992
|
},
|
|
7635
7993
|
required: [],
|
|
@@ -7638,25 +7996,25 @@ var MANIFEST = [
|
|
|
7638
7996
|
},
|
|
7639
7997
|
{
|
|
7640
7998
|
name: "hover",
|
|
7641
|
-
description: "
|
|
7999
|
+
description: "Hover an element by UID or CSS selector; provide exactly one.",
|
|
7642
8000
|
inputSchema: {
|
|
7643
8001
|
type: "object",
|
|
7644
8002
|
properties: {
|
|
7645
8003
|
lease: {
|
|
7646
8004
|
type: "string",
|
|
7647
|
-
description: "Lease token
|
|
8005
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7648
8006
|
},
|
|
7649
8007
|
target: {
|
|
7650
8008
|
type: "string",
|
|
7651
|
-
description: "Page selector
|
|
8009
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7652
8010
|
},
|
|
7653
8011
|
uid: {
|
|
7654
8012
|
type: "number",
|
|
7655
|
-
description: "
|
|
8013
|
+
description: "Element backendDOMNodeId."
|
|
7656
8014
|
},
|
|
7657
8015
|
selector: {
|
|
7658
8016
|
type: "string",
|
|
7659
|
-
description: "CSS selector
|
|
8017
|
+
description: "CSS selector."
|
|
7660
8018
|
}
|
|
7661
8019
|
},
|
|
7662
8020
|
required: [],
|
|
@@ -7665,67 +8023,67 @@ var MANIFEST = [
|
|
|
7665
8023
|
},
|
|
7666
8024
|
{
|
|
7667
8025
|
name: "drag",
|
|
7668
|
-
description: "
|
|
8026
|
+
description: "Drag from an element to a destination or offset; html5 mode is Chrome-only.",
|
|
7669
8027
|
inputSchema: {
|
|
7670
8028
|
type: "object",
|
|
7671
8029
|
properties: {
|
|
7672
8030
|
lease: {
|
|
7673
8031
|
type: "string",
|
|
7674
|
-
description: "Lease token
|
|
8032
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7675
8033
|
},
|
|
7676
8034
|
target: {
|
|
7677
8035
|
type: "string",
|
|
7678
|
-
description: "Page selector
|
|
8036
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7679
8037
|
},
|
|
7680
8038
|
from: {
|
|
7681
8039
|
type: "object",
|
|
7682
|
-
description: "
|
|
8040
|
+
description: "Drag source.",
|
|
7683
8041
|
properties: {
|
|
7684
8042
|
uid: {
|
|
7685
8043
|
type: "number",
|
|
7686
|
-
description: "
|
|
8044
|
+
description: "Element backendDOMNodeId."
|
|
7687
8045
|
},
|
|
7688
8046
|
selector: {
|
|
7689
8047
|
type: "string",
|
|
7690
|
-
description: "CSS selector
|
|
8048
|
+
description: "CSS selector."
|
|
7691
8049
|
}
|
|
7692
8050
|
},
|
|
7693
8051
|
additionalProperties: false
|
|
7694
8052
|
},
|
|
7695
8053
|
to: {
|
|
7696
8054
|
type: "object",
|
|
7697
|
-
description: "
|
|
8055
|
+
description: "Drag destination.",
|
|
7698
8056
|
properties: {
|
|
7699
8057
|
uid: {
|
|
7700
8058
|
type: "number",
|
|
7701
|
-
description: "
|
|
8059
|
+
description: "Element backendDOMNodeId."
|
|
7702
8060
|
},
|
|
7703
8061
|
selector: {
|
|
7704
8062
|
type: "string",
|
|
7705
|
-
description: "CSS selector
|
|
8063
|
+
description: "CSS selector."
|
|
7706
8064
|
},
|
|
7707
8065
|
x: {
|
|
7708
8066
|
type: "number",
|
|
7709
|
-
description: "
|
|
8067
|
+
description: "Viewport x-coordinate."
|
|
7710
8068
|
},
|
|
7711
8069
|
y: {
|
|
7712
8070
|
type: "number",
|
|
7713
|
-
description: "
|
|
8071
|
+
description: "Viewport y-coordinate."
|
|
7714
8072
|
}
|
|
7715
8073
|
},
|
|
7716
8074
|
additionalProperties: false
|
|
7717
8075
|
},
|
|
7718
8076
|
by: {
|
|
7719
8077
|
type: "object",
|
|
7720
|
-
description: "
|
|
8078
|
+
description: "Drag offset.",
|
|
7721
8079
|
properties: {
|
|
7722
8080
|
dx: {
|
|
7723
8081
|
type: "number",
|
|
7724
|
-
description: "Horizontal offset
|
|
8082
|
+
description: "Horizontal drag offset."
|
|
7725
8083
|
},
|
|
7726
8084
|
dy: {
|
|
7727
8085
|
type: "number",
|
|
7728
|
-
description: "Vertical offset
|
|
8086
|
+
description: "Vertical drag offset."
|
|
7729
8087
|
}
|
|
7730
8088
|
},
|
|
7731
8089
|
additionalProperties: false
|
|
@@ -7736,11 +8094,11 @@ var MANIFEST = [
|
|
|
7736
8094
|
"mouse",
|
|
7737
8095
|
"html5"
|
|
7738
8096
|
],
|
|
7739
|
-
description: "
|
|
8097
|
+
description: "Drag mode."
|
|
7740
8098
|
},
|
|
7741
8099
|
steps: {
|
|
7742
8100
|
type: "number",
|
|
7743
|
-
description: "
|
|
8101
|
+
description: "Interpolation steps."
|
|
7744
8102
|
}
|
|
7745
8103
|
},
|
|
7746
8104
|
required: [
|
|
@@ -7751,41 +8109,41 @@ var MANIFEST = [
|
|
|
7751
8109
|
},
|
|
7752
8110
|
{
|
|
7753
8111
|
name: "scroll",
|
|
7754
|
-
description: "
|
|
8112
|
+
description: "Dispatch a wheel event at an element or coordinate anchor; provide deltaX or deltaY.",
|
|
7755
8113
|
inputSchema: {
|
|
7756
8114
|
type: "object",
|
|
7757
8115
|
properties: {
|
|
7758
8116
|
lease: {
|
|
7759
8117
|
type: "string",
|
|
7760
|
-
description: "Lease token
|
|
8118
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7761
8119
|
},
|
|
7762
8120
|
target: {
|
|
7763
8121
|
type: "string",
|
|
7764
|
-
description: "Page selector
|
|
8122
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7765
8123
|
},
|
|
7766
8124
|
uid: {
|
|
7767
8125
|
type: "number",
|
|
7768
|
-
description: "
|
|
8126
|
+
description: "Element backendDOMNodeId."
|
|
7769
8127
|
},
|
|
7770
8128
|
selector: {
|
|
7771
8129
|
type: "string",
|
|
7772
|
-
description: "CSS selector
|
|
8130
|
+
description: "CSS selector."
|
|
7773
8131
|
},
|
|
7774
8132
|
x: {
|
|
7775
8133
|
type: "number",
|
|
7776
|
-
description: "
|
|
8134
|
+
description: "Viewport x-coordinate."
|
|
7777
8135
|
},
|
|
7778
8136
|
y: {
|
|
7779
8137
|
type: "number",
|
|
7780
|
-
description: "
|
|
8138
|
+
description: "Viewport y-coordinate."
|
|
7781
8139
|
},
|
|
7782
8140
|
deltaX: {
|
|
7783
8141
|
type: "number",
|
|
7784
|
-
description: "Horizontal scroll delta
|
|
8142
|
+
description: "Horizontal scroll delta."
|
|
7785
8143
|
},
|
|
7786
8144
|
deltaY: {
|
|
7787
8145
|
type: "number",
|
|
7788
|
-
description: "Vertical scroll delta
|
|
8146
|
+
description: "Vertical scroll delta."
|
|
7789
8147
|
}
|
|
7790
8148
|
},
|
|
7791
8149
|
required: [],
|
|
@@ -7794,17 +8152,17 @@ var MANIFEST = [
|
|
|
7794
8152
|
},
|
|
7795
8153
|
{
|
|
7796
8154
|
name: "dispatch_mouse",
|
|
7797
|
-
description: "
|
|
8155
|
+
description: "Dispatch one raw mouse event at viewport coordinates; Chrome-only.",
|
|
7798
8156
|
inputSchema: {
|
|
7799
8157
|
type: "object",
|
|
7800
8158
|
properties: {
|
|
7801
8159
|
lease: {
|
|
7802
8160
|
type: "string",
|
|
7803
|
-
description: "Lease token
|
|
8161
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7804
8162
|
},
|
|
7805
8163
|
target: {
|
|
7806
8164
|
type: "string",
|
|
7807
|
-
description: "Page selector
|
|
8165
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7808
8166
|
},
|
|
7809
8167
|
action: {
|
|
7810
8168
|
type: "string",
|
|
@@ -7813,15 +8171,15 @@ var MANIFEST = [
|
|
|
7813
8171
|
"down",
|
|
7814
8172
|
"up"
|
|
7815
8173
|
],
|
|
7816
|
-
description: "
|
|
8174
|
+
description: "Mouse action."
|
|
7817
8175
|
},
|
|
7818
8176
|
x: {
|
|
7819
8177
|
type: "number",
|
|
7820
|
-
description: "Viewport x-coordinate.
|
|
8178
|
+
description: "Viewport x-coordinate."
|
|
7821
8179
|
},
|
|
7822
8180
|
y: {
|
|
7823
8181
|
type: "number",
|
|
7824
|
-
description: "Viewport y-coordinate.
|
|
8182
|
+
description: "Viewport y-coordinate."
|
|
7825
8183
|
},
|
|
7826
8184
|
button: {
|
|
7827
8185
|
type: "string",
|
|
@@ -7830,11 +8188,11 @@ var MANIFEST = [
|
|
|
7830
8188
|
"right",
|
|
7831
8189
|
"middle"
|
|
7832
8190
|
],
|
|
7833
|
-
description: "Mouse button
|
|
8191
|
+
description: "Mouse button."
|
|
7834
8192
|
},
|
|
7835
8193
|
clickCount: {
|
|
7836
8194
|
type: "number",
|
|
7837
|
-
description: "Click
|
|
8195
|
+
description: "Click count."
|
|
7838
8196
|
},
|
|
7839
8197
|
modifiers: {
|
|
7840
8198
|
type: "array",
|
|
@@ -7847,7 +8205,7 @@ var MANIFEST = [
|
|
|
7847
8205
|
"Shift"
|
|
7848
8206
|
]
|
|
7849
8207
|
},
|
|
7850
|
-
description: "Modifier keys
|
|
8208
|
+
description: "Modifier keys: Control|Ctrl|Shift|Alt|Meta|Cmd."
|
|
7851
8209
|
}
|
|
7852
8210
|
},
|
|
7853
8211
|
required: [
|
|
@@ -7860,25 +8218,25 @@ var MANIFEST = [
|
|
|
7860
8218
|
},
|
|
7861
8219
|
{
|
|
7862
8220
|
name: "wait_for_download",
|
|
7863
|
-
description: "
|
|
8221
|
+
description: "Arm or collect a browser download; arm capture before triggering the download.",
|
|
7864
8222
|
inputSchema: {
|
|
7865
8223
|
type: "object",
|
|
7866
8224
|
properties: {
|
|
7867
8225
|
lease: {
|
|
7868
8226
|
type: "string",
|
|
7869
|
-
description: "Lease token
|
|
8227
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7870
8228
|
},
|
|
7871
8229
|
target: {
|
|
7872
8230
|
type: "string",
|
|
7873
|
-
description: "
|
|
8231
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7874
8232
|
},
|
|
7875
8233
|
arm: {
|
|
7876
8234
|
type: "boolean",
|
|
7877
|
-
description: "Arm download capture
|
|
8235
|
+
description: "Arm download capture."
|
|
7878
8236
|
},
|
|
7879
8237
|
timeoutMs: {
|
|
7880
8238
|
type: "number",
|
|
7881
|
-
description: "
|
|
8239
|
+
description: "Timeout in milliseconds."
|
|
7882
8240
|
}
|
|
7883
8241
|
},
|
|
7884
8242
|
required: [],
|
|
@@ -7887,32 +8245,32 @@ var MANIFEST = [
|
|
|
7887
8245
|
},
|
|
7888
8246
|
{
|
|
7889
8247
|
name: "grant_permissions",
|
|
7890
|
-
description: "Grant
|
|
8248
|
+
description: "Grant or reset browser permissions; permissions are origin-scoped and Chrome-only.",
|
|
7891
8249
|
inputSchema: {
|
|
7892
8250
|
type: "object",
|
|
7893
8251
|
properties: {
|
|
7894
8252
|
lease: {
|
|
7895
8253
|
type: "string",
|
|
7896
|
-
description: "Lease token
|
|
8254
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7897
8255
|
},
|
|
7898
8256
|
target: {
|
|
7899
8257
|
type: "string",
|
|
7900
|
-
description: "
|
|
8258
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7901
8259
|
},
|
|
7902
8260
|
permissions: {
|
|
7903
8261
|
type: "array",
|
|
7904
8262
|
items: {
|
|
7905
8263
|
type: "string"
|
|
7906
8264
|
},
|
|
7907
|
-
description: "CDP PermissionType values
|
|
8265
|
+
description: "CDP PermissionType values, e.g. geolocation|notifications|clipboardReadWrite."
|
|
7908
8266
|
},
|
|
7909
8267
|
origin: {
|
|
7910
8268
|
type: "string",
|
|
7911
|
-
description: "
|
|
8269
|
+
description: "Permission origin."
|
|
7912
8270
|
},
|
|
7913
8271
|
reset: {
|
|
7914
8272
|
type: "boolean",
|
|
7915
|
-
description: "
|
|
8273
|
+
description: "Reset permission grants."
|
|
7916
8274
|
}
|
|
7917
8275
|
},
|
|
7918
8276
|
required: [],
|
|
@@ -7921,25 +8279,25 @@ var MANIFEST = [
|
|
|
7921
8279
|
},
|
|
7922
8280
|
{
|
|
7923
8281
|
name: "fill",
|
|
7924
|
-
description: "
|
|
8282
|
+
description: "Replace an element contents; provide exactly one of UID or selector.",
|
|
7925
8283
|
inputSchema: {
|
|
7926
8284
|
type: "object",
|
|
7927
8285
|
properties: {
|
|
7928
8286
|
lease: {
|
|
7929
8287
|
type: "string",
|
|
7930
|
-
description: "Lease token
|
|
8288
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7931
8289
|
},
|
|
7932
8290
|
target: {
|
|
7933
8291
|
type: "string",
|
|
7934
|
-
description: "Page selector
|
|
8292
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7935
8293
|
},
|
|
7936
8294
|
uid: {
|
|
7937
8295
|
type: "number",
|
|
7938
|
-
description: "
|
|
8296
|
+
description: "Element backendDOMNodeId."
|
|
7939
8297
|
},
|
|
7940
8298
|
selector: {
|
|
7941
8299
|
type: "string",
|
|
7942
|
-
description: "CSS selector
|
|
8300
|
+
description: "CSS selector."
|
|
7943
8301
|
},
|
|
7944
8302
|
value: {
|
|
7945
8303
|
type: "string",
|
|
@@ -7954,35 +8312,35 @@ var MANIFEST = [
|
|
|
7954
8312
|
},
|
|
7955
8313
|
{
|
|
7956
8314
|
name: "fill_form",
|
|
7957
|
-
description: "
|
|
8315
|
+
description: "Fill multiple elements atomically; each field needs a UID or selector.",
|
|
7958
8316
|
inputSchema: {
|
|
7959
8317
|
type: "object",
|
|
7960
8318
|
properties: {
|
|
7961
8319
|
lease: {
|
|
7962
8320
|
type: "string",
|
|
7963
|
-
description: "Lease token
|
|
8321
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
7964
8322
|
},
|
|
7965
8323
|
target: {
|
|
7966
8324
|
type: "string",
|
|
7967
|
-
description: "Page selector
|
|
8325
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
7968
8326
|
},
|
|
7969
8327
|
fields: {
|
|
7970
8328
|
type: "array",
|
|
7971
|
-
description: "
|
|
8329
|
+
description: "Form fields to fill.",
|
|
7972
8330
|
items: {
|
|
7973
8331
|
type: "object",
|
|
7974
8332
|
properties: {
|
|
7975
8333
|
uid: {
|
|
7976
8334
|
type: "number",
|
|
7977
|
-
description: "
|
|
8335
|
+
description: "Element backendDOMNodeId."
|
|
7978
8336
|
},
|
|
7979
8337
|
selector: {
|
|
7980
8338
|
type: "string",
|
|
7981
|
-
description: "CSS selector
|
|
8339
|
+
description: "CSS selector."
|
|
7982
8340
|
},
|
|
7983
8341
|
value: {
|
|
7984
8342
|
type: "string",
|
|
7985
|
-
description: "
|
|
8343
|
+
description: "Text value to set; the field is cleared first, overwriting existing content."
|
|
7986
8344
|
}
|
|
7987
8345
|
},
|
|
7988
8346
|
required: [
|
|
@@ -8000,29 +8358,29 @@ var MANIFEST = [
|
|
|
8000
8358
|
},
|
|
8001
8359
|
{
|
|
8002
8360
|
name: "type_text",
|
|
8003
|
-
description: "
|
|
8361
|
+
description: "Append text to an element; input is atomic and does not clear existing content.",
|
|
8004
8362
|
inputSchema: {
|
|
8005
8363
|
type: "object",
|
|
8006
8364
|
properties: {
|
|
8007
8365
|
lease: {
|
|
8008
8366
|
type: "string",
|
|
8009
|
-
description: "Lease token
|
|
8367
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8010
8368
|
},
|
|
8011
8369
|
target: {
|
|
8012
8370
|
type: "string",
|
|
8013
|
-
description: "Page selector
|
|
8371
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8014
8372
|
},
|
|
8015
8373
|
uid: {
|
|
8016
8374
|
type: "number",
|
|
8017
|
-
description: "
|
|
8375
|
+
description: "Element backendDOMNodeId."
|
|
8018
8376
|
},
|
|
8019
8377
|
selector: {
|
|
8020
8378
|
type: "string",
|
|
8021
|
-
description: "CSS selector
|
|
8379
|
+
description: "CSS selector."
|
|
8022
8380
|
},
|
|
8023
8381
|
text: {
|
|
8024
8382
|
type: "string",
|
|
8025
|
-
description: "Text
|
|
8383
|
+
description: "Text substring."
|
|
8026
8384
|
}
|
|
8027
8385
|
},
|
|
8028
8386
|
required: [
|
|
@@ -8033,25 +8391,25 @@ var MANIFEST = [
|
|
|
8033
8391
|
},
|
|
8034
8392
|
{
|
|
8035
8393
|
name: "press_key",
|
|
8036
|
-
description: "
|
|
8394
|
+
description: "Press one named key or printable character with modifiers; no F-keys or IME.",
|
|
8037
8395
|
inputSchema: {
|
|
8038
8396
|
type: "object",
|
|
8039
8397
|
properties: {
|
|
8040
8398
|
lease: {
|
|
8041
8399
|
type: "string",
|
|
8042
|
-
description: "Lease token
|
|
8400
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8043
8401
|
},
|
|
8044
8402
|
target: {
|
|
8045
8403
|
type: "string",
|
|
8046
|
-
description: "Page selector
|
|
8404
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8047
8405
|
},
|
|
8048
8406
|
key: {
|
|
8049
8407
|
type: "string",
|
|
8050
|
-
description: "
|
|
8408
|
+
description: "Named key or printable character; e.g. Enter|Tab|Escape|ArrowDown|Backspace."
|
|
8051
8409
|
},
|
|
8052
8410
|
modifiers: {
|
|
8053
8411
|
type: "array",
|
|
8054
|
-
description: "Modifier
|
|
8412
|
+
description: "Modifier keys: Control|Ctrl|Shift|Alt|Meta|Cmd.",
|
|
8055
8413
|
items: {
|
|
8056
8414
|
type: "string"
|
|
8057
8415
|
}
|
|
@@ -8065,32 +8423,32 @@ var MANIFEST = [
|
|
|
8065
8423
|
},
|
|
8066
8424
|
{
|
|
8067
8425
|
name: "upload_file",
|
|
8068
|
-
description: "
|
|
8426
|
+
description: "Attach absolute file paths to a file input; provide an array.",
|
|
8069
8427
|
inputSchema: {
|
|
8070
8428
|
type: "object",
|
|
8071
8429
|
properties: {
|
|
8072
8430
|
lease: {
|
|
8073
8431
|
type: "string",
|
|
8074
|
-
description: "Lease token
|
|
8432
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8075
8433
|
},
|
|
8076
8434
|
target: {
|
|
8077
8435
|
type: "string",
|
|
8078
|
-
description: "Page selector
|
|
8436
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8079
8437
|
},
|
|
8080
8438
|
uid: {
|
|
8081
8439
|
type: "number",
|
|
8082
|
-
description: "
|
|
8440
|
+
description: "Element backendDOMNodeId."
|
|
8083
8441
|
},
|
|
8084
8442
|
selector: {
|
|
8085
8443
|
type: "string",
|
|
8086
|
-
description: "CSS selector
|
|
8444
|
+
description: "CSS selector."
|
|
8087
8445
|
},
|
|
8088
8446
|
files: {
|
|
8089
8447
|
type: "array",
|
|
8090
8448
|
items: {
|
|
8091
8449
|
type: "string"
|
|
8092
8450
|
},
|
|
8093
|
-
description:
|
|
8451
|
+
description: "Absolute file paths."
|
|
8094
8452
|
}
|
|
8095
8453
|
},
|
|
8096
8454
|
required: [
|
|
@@ -8101,17 +8459,17 @@ var MANIFEST = [
|
|
|
8101
8459
|
},
|
|
8102
8460
|
{
|
|
8103
8461
|
name: "take_screenshot",
|
|
8104
|
-
description: "
|
|
8462
|
+
description: "Capture a viewport, full page, or element to PNG/JPEG; oversized captures may be tiled.",
|
|
8105
8463
|
inputSchema: {
|
|
8106
8464
|
type: "object",
|
|
8107
8465
|
properties: {
|
|
8108
8466
|
lease: {
|
|
8109
8467
|
type: "string",
|
|
8110
|
-
description: "Lease token
|
|
8468
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8111
8469
|
},
|
|
8112
8470
|
target: {
|
|
8113
8471
|
type: "string",
|
|
8114
|
-
description: "Page selector
|
|
8472
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8115
8473
|
},
|
|
8116
8474
|
format: {
|
|
8117
8475
|
type: "string",
|
|
@@ -8119,47 +8477,47 @@ var MANIFEST = [
|
|
|
8119
8477
|
"png",
|
|
8120
8478
|
"jpeg"
|
|
8121
8479
|
],
|
|
8122
|
-
description: "Image format
|
|
8480
|
+
description: "Image/frame format."
|
|
8123
8481
|
},
|
|
8124
8482
|
quality: {
|
|
8125
8483
|
type: "number",
|
|
8126
|
-
description: "JPEG quality 0-100
|
|
8484
|
+
description: "JPEG quality 0-100."
|
|
8127
8485
|
},
|
|
8128
8486
|
fullPage: {
|
|
8129
8487
|
type: "boolean",
|
|
8130
|
-
description: "Capture
|
|
8488
|
+
description: "Capture full scrollable page."
|
|
8131
8489
|
},
|
|
8132
8490
|
scale: {
|
|
8133
8491
|
type: "number",
|
|
8134
|
-
description: "Output
|
|
8492
|
+
description: "Output scale (0<scale<=8)."
|
|
8135
8493
|
},
|
|
8136
8494
|
renderWidth: {
|
|
8137
8495
|
type: "number",
|
|
8138
|
-
description: "
|
|
8496
|
+
description: "Rendered viewport width."
|
|
8139
8497
|
},
|
|
8140
8498
|
renderHeight: {
|
|
8141
8499
|
type: "number",
|
|
8142
|
-
description: "
|
|
8500
|
+
description: "Rendered viewport height."
|
|
8143
8501
|
},
|
|
8144
8502
|
tile: {
|
|
8145
8503
|
type: "boolean",
|
|
8146
|
-
description: "
|
|
8504
|
+
description: "Vertical-band stitching."
|
|
8147
8505
|
},
|
|
8148
8506
|
uid: {
|
|
8149
8507
|
type: "number",
|
|
8150
|
-
description: "Element
|
|
8508
|
+
description: "Element backendDOMNodeId."
|
|
8151
8509
|
},
|
|
8152
8510
|
selector: {
|
|
8153
8511
|
type: "string",
|
|
8154
|
-
description: "CSS selector
|
|
8512
|
+
description: "CSS selector."
|
|
8155
8513
|
},
|
|
8156
8514
|
savePath: {
|
|
8157
8515
|
type: "string",
|
|
8158
|
-
description: "
|
|
8516
|
+
description: "Output file path."
|
|
8159
8517
|
},
|
|
8160
8518
|
returnBase64: {
|
|
8161
8519
|
type: "boolean",
|
|
8162
|
-
description: "
|
|
8520
|
+
description: "Return base64 bytes."
|
|
8163
8521
|
}
|
|
8164
8522
|
},
|
|
8165
8523
|
required: [],
|
|
@@ -8168,49 +8526,49 @@ var MANIFEST = [
|
|
|
8168
8526
|
},
|
|
8169
8527
|
{
|
|
8170
8528
|
name: "emulate",
|
|
8171
|
-
description: "
|
|
8529
|
+
description: "Apply browser emulation overrides; width and height must be paired.",
|
|
8172
8530
|
inputSchema: {
|
|
8173
8531
|
type: "object",
|
|
8174
8532
|
properties: {
|
|
8175
8533
|
lease: {
|
|
8176
8534
|
type: "string",
|
|
8177
|
-
description: "Lease token
|
|
8535
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8178
8536
|
},
|
|
8179
8537
|
target: {
|
|
8180
8538
|
type: "string",
|
|
8181
|
-
description: "Page selector
|
|
8539
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8182
8540
|
},
|
|
8183
8541
|
width: {
|
|
8184
8542
|
type: "number",
|
|
8185
|
-
description: "
|
|
8543
|
+
description: "Viewport width; pair with height."
|
|
8186
8544
|
},
|
|
8187
8545
|
height: {
|
|
8188
8546
|
type: "number",
|
|
8189
|
-
description: "
|
|
8547
|
+
description: "Viewport height; pair with width."
|
|
8190
8548
|
},
|
|
8191
8549
|
deviceScaleFactor: {
|
|
8192
8550
|
type: "number",
|
|
8193
|
-
description: "Device pixel ratio
|
|
8551
|
+
description: "Device pixel ratio."
|
|
8194
8552
|
},
|
|
8195
8553
|
mobile: {
|
|
8196
8554
|
type: "boolean",
|
|
8197
|
-
description: "
|
|
8555
|
+
description: "Mobile emulation."
|
|
8198
8556
|
},
|
|
8199
8557
|
userAgent: {
|
|
8200
8558
|
type: "string",
|
|
8201
|
-
description: "User-Agent
|
|
8559
|
+
description: "User-Agent override."
|
|
8202
8560
|
},
|
|
8203
8561
|
cpuThrottlingRate: {
|
|
8204
8562
|
type: "number",
|
|
8205
|
-
description: "CPU throttling
|
|
8563
|
+
description: "CPU throttling rate (>=1)."
|
|
8206
8564
|
},
|
|
8207
8565
|
media: {
|
|
8208
8566
|
type: "string",
|
|
8209
|
-
description: "
|
|
8567
|
+
description: "CSS media: screen|print|blank."
|
|
8210
8568
|
},
|
|
8211
8569
|
mediaFeatures: {
|
|
8212
8570
|
type: "array",
|
|
8213
|
-
description: "
|
|
8571
|
+
description: "CSS media feature overrides.",
|
|
8214
8572
|
items: {
|
|
8215
8573
|
type: "object",
|
|
8216
8574
|
properties: {
|
|
@@ -8220,7 +8578,7 @@ var MANIFEST = [
|
|
|
8220
8578
|
},
|
|
8221
8579
|
value: {
|
|
8222
8580
|
type: "string",
|
|
8223
|
-
description: "
|
|
8581
|
+
description: "Feature value, e.g. 'dark'."
|
|
8224
8582
|
}
|
|
8225
8583
|
},
|
|
8226
8584
|
required: [
|
|
@@ -8232,34 +8590,34 @@ var MANIFEST = [
|
|
|
8232
8590
|
},
|
|
8233
8591
|
networkConditions: {
|
|
8234
8592
|
type: "object",
|
|
8235
|
-
description: "Network overrides
|
|
8593
|
+
description: "Network condition overrides.",
|
|
8236
8594
|
properties: {
|
|
8237
8595
|
offline: {
|
|
8238
8596
|
type: "boolean",
|
|
8239
|
-
description: "
|
|
8597
|
+
description: "Simulate offline."
|
|
8240
8598
|
},
|
|
8241
8599
|
latency: {
|
|
8242
8600
|
type: "number",
|
|
8243
|
-
description: "
|
|
8601
|
+
description: "Network latency in milliseconds."
|
|
8244
8602
|
},
|
|
8245
8603
|
downloadThroughput: {
|
|
8246
8604
|
type: "number",
|
|
8247
|
-
description: "
|
|
8605
|
+
description: "Download throughput; -1 unlimited."
|
|
8248
8606
|
},
|
|
8249
8607
|
uploadThroughput: {
|
|
8250
8608
|
type: "number",
|
|
8251
|
-
description: "
|
|
8609
|
+
description: "Upload throughput; -1 unlimited."
|
|
8252
8610
|
},
|
|
8253
8611
|
connectionType: {
|
|
8254
8612
|
type: "string",
|
|
8255
|
-
description: "Connection
|
|
8613
|
+
description: "Connection: none|cellular2g|cellular3g|cellular4g|bluetooth|ethernet|wifi|wimax|other."
|
|
8256
8614
|
}
|
|
8257
8615
|
},
|
|
8258
8616
|
additionalProperties: false
|
|
8259
8617
|
},
|
|
8260
8618
|
clearOverrides: {
|
|
8261
8619
|
type: "boolean",
|
|
8262
|
-
description: "
|
|
8620
|
+
description: "Clear all emulation overrides."
|
|
8263
8621
|
}
|
|
8264
8622
|
},
|
|
8265
8623
|
required: [],
|
|
@@ -8268,33 +8626,33 @@ var MANIFEST = [
|
|
|
8268
8626
|
},
|
|
8269
8627
|
{
|
|
8270
8628
|
name: "resize_page",
|
|
8271
|
-
description: "
|
|
8629
|
+
description: "Set and verify page viewport metrics; width and height are required.",
|
|
8272
8630
|
inputSchema: {
|
|
8273
8631
|
type: "object",
|
|
8274
8632
|
properties: {
|
|
8275
8633
|
lease: {
|
|
8276
8634
|
type: "string",
|
|
8277
|
-
description: "Lease token
|
|
8635
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8278
8636
|
},
|
|
8279
8637
|
target: {
|
|
8280
8638
|
type: "string",
|
|
8281
|
-
description: "Page selector
|
|
8639
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8282
8640
|
},
|
|
8283
8641
|
width: {
|
|
8284
8642
|
type: "number",
|
|
8285
|
-
description: "Viewport width
|
|
8643
|
+
description: "Viewport width; pair with height."
|
|
8286
8644
|
},
|
|
8287
8645
|
height: {
|
|
8288
8646
|
type: "number",
|
|
8289
|
-
description: "Viewport height
|
|
8647
|
+
description: "Viewport height; pair with width."
|
|
8290
8648
|
},
|
|
8291
8649
|
deviceScaleFactor: {
|
|
8292
8650
|
type: "number",
|
|
8293
|
-
description: "Device pixel ratio
|
|
8651
|
+
description: "Device pixel ratio."
|
|
8294
8652
|
},
|
|
8295
8653
|
mobile: {
|
|
8296
8654
|
type: "boolean",
|
|
8297
|
-
description: "
|
|
8655
|
+
description: "Mobile emulation."
|
|
8298
8656
|
}
|
|
8299
8657
|
},
|
|
8300
8658
|
required: [
|
|
@@ -8306,33 +8664,33 @@ var MANIFEST = [
|
|
|
8306
8664
|
},
|
|
8307
8665
|
{
|
|
8308
8666
|
name: "handle_dialog",
|
|
8309
|
-
description: "
|
|
8667
|
+
description: "Handle the next JavaScript dialog; autoMs switches to timed multi-dialog mode.",
|
|
8310
8668
|
inputSchema: {
|
|
8311
8669
|
type: "object",
|
|
8312
8670
|
properties: {
|
|
8313
8671
|
lease: {
|
|
8314
8672
|
type: "string",
|
|
8315
|
-
description: "Lease token
|
|
8673
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8316
8674
|
},
|
|
8317
8675
|
target: {
|
|
8318
8676
|
type: "string",
|
|
8319
|
-
description: "Page selector
|
|
8677
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8320
8678
|
},
|
|
8321
8679
|
accept: {
|
|
8322
8680
|
type: "boolean",
|
|
8323
|
-
description: "
|
|
8681
|
+
description: "Accept or dismiss dialog."
|
|
8324
8682
|
},
|
|
8325
8683
|
promptText: {
|
|
8326
8684
|
type: "string",
|
|
8327
|
-
description: "
|
|
8685
|
+
description: "Prompt response text."
|
|
8328
8686
|
},
|
|
8329
8687
|
timeoutMs: {
|
|
8330
8688
|
type: "number",
|
|
8331
|
-
description: "
|
|
8689
|
+
description: "Timeout in milliseconds."
|
|
8332
8690
|
},
|
|
8333
8691
|
autoMs: {
|
|
8334
8692
|
type: "number",
|
|
8335
|
-
description: "
|
|
8693
|
+
description: "Multi-dialog window in milliseconds."
|
|
8336
8694
|
}
|
|
8337
8695
|
},
|
|
8338
8696
|
required: [
|
|
@@ -8343,29 +8701,29 @@ var MANIFEST = [
|
|
|
8343
8701
|
},
|
|
8344
8702
|
{
|
|
8345
8703
|
name: "list_console_messages",
|
|
8346
|
-
description: "Read
|
|
8704
|
+
description: "Read or recapture console messages for a page or worker; worker capture is Chrome-only.",
|
|
8347
8705
|
inputSchema: {
|
|
8348
8706
|
type: "object",
|
|
8349
8707
|
properties: {
|
|
8350
8708
|
lease: {
|
|
8351
8709
|
type: "string",
|
|
8352
|
-
description: "Lease token
|
|
8710
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8353
8711
|
},
|
|
8354
8712
|
target: {
|
|
8355
8713
|
type: "string",
|
|
8356
|
-
description: "Page selector
|
|
8714
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8357
8715
|
},
|
|
8358
8716
|
reload: {
|
|
8359
8717
|
type: "boolean",
|
|
8360
|
-
description: "
|
|
8718
|
+
description: "Reload before capture."
|
|
8361
8719
|
},
|
|
8362
8720
|
durationMs: {
|
|
8363
8721
|
type: "number",
|
|
8364
|
-
description: "Capture
|
|
8722
|
+
description: "Capture duration in milliseconds."
|
|
8365
8723
|
},
|
|
8366
8724
|
wake: {
|
|
8367
8725
|
type: "boolean",
|
|
8368
|
-
description: "
|
|
8726
|
+
description: "Wake worker before capture."
|
|
8369
8727
|
}
|
|
8370
8728
|
},
|
|
8371
8729
|
required: [],
|
|
@@ -8374,21 +8732,21 @@ var MANIFEST = [
|
|
|
8374
8732
|
},
|
|
8375
8733
|
{
|
|
8376
8734
|
name: "get_console_message",
|
|
8377
|
-
description: "Return one console entry by zero-based index from the
|
|
8735
|
+
description: "Return one console entry by zero-based index from the existing buffer.",
|
|
8378
8736
|
inputSchema: {
|
|
8379
8737
|
type: "object",
|
|
8380
8738
|
properties: {
|
|
8381
8739
|
lease: {
|
|
8382
8740
|
type: "string",
|
|
8383
|
-
description: "Lease token
|
|
8741
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8384
8742
|
},
|
|
8385
8743
|
target: {
|
|
8386
8744
|
type: "string",
|
|
8387
|
-
description: "Page selector
|
|
8745
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8388
8746
|
},
|
|
8389
8747
|
index: {
|
|
8390
8748
|
type: "number",
|
|
8391
|
-
description: "Zero-based index
|
|
8749
|
+
description: "Zero-based entry index."
|
|
8392
8750
|
}
|
|
8393
8751
|
},
|
|
8394
8752
|
required: [],
|
|
@@ -8397,33 +8755,33 @@ var MANIFEST = [
|
|
|
8397
8755
|
},
|
|
8398
8756
|
{
|
|
8399
8757
|
name: "list_network_requests",
|
|
8400
|
-
description: "
|
|
8758
|
+
description: "Read or recapture correlated network requests; worker capture is Chrome-only.",
|
|
8401
8759
|
inputSchema: {
|
|
8402
8760
|
type: "object",
|
|
8403
8761
|
properties: {
|
|
8404
8762
|
lease: {
|
|
8405
8763
|
type: "string",
|
|
8406
|
-
description: "Lease token
|
|
8764
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8407
8765
|
},
|
|
8408
8766
|
target: {
|
|
8409
8767
|
type: "string",
|
|
8410
|
-
description: "Page selector
|
|
8768
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8411
8769
|
},
|
|
8412
8770
|
reload: {
|
|
8413
8771
|
type: "boolean",
|
|
8414
|
-
description: "
|
|
8772
|
+
description: "Reload before capture."
|
|
8415
8773
|
},
|
|
8416
8774
|
durationMs: {
|
|
8417
8775
|
type: "number",
|
|
8418
|
-
description: "Capture
|
|
8776
|
+
description: "Capture duration in milliseconds."
|
|
8419
8777
|
},
|
|
8420
8778
|
filterUrl: {
|
|
8421
8779
|
type: "string",
|
|
8422
|
-
description: "
|
|
8780
|
+
description: "URL substring filter."
|
|
8423
8781
|
},
|
|
8424
8782
|
wake: {
|
|
8425
8783
|
type: "boolean",
|
|
8426
|
-
description: "
|
|
8784
|
+
description: "Wake worker before capture."
|
|
8427
8785
|
}
|
|
8428
8786
|
},
|
|
8429
8787
|
required: [],
|
|
@@ -8432,37 +8790,37 @@ var MANIFEST = [
|
|
|
8432
8790
|
},
|
|
8433
8791
|
{
|
|
8434
8792
|
name: "get_network_request",
|
|
8435
|
-
description: "Return
|
|
8793
|
+
description: "Return a network request by ID or URL; body capture requires URL.",
|
|
8436
8794
|
inputSchema: {
|
|
8437
8795
|
type: "object",
|
|
8438
8796
|
properties: {
|
|
8439
8797
|
lease: {
|
|
8440
8798
|
type: "string",
|
|
8441
|
-
description: "Lease token
|
|
8799
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8442
8800
|
},
|
|
8443
8801
|
target: {
|
|
8444
8802
|
type: "string",
|
|
8445
|
-
description: "Page selector
|
|
8803
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8446
8804
|
},
|
|
8447
8805
|
requestId: {
|
|
8448
8806
|
type: "string",
|
|
8449
|
-
description: "
|
|
8807
|
+
description: "Exact request ID."
|
|
8450
8808
|
},
|
|
8451
8809
|
url: {
|
|
8452
8810
|
type: "string",
|
|
8453
|
-
description: "
|
|
8811
|
+
description: "URL value."
|
|
8454
8812
|
},
|
|
8455
8813
|
includeBody: {
|
|
8456
8814
|
type: "boolean",
|
|
8457
|
-
description: "
|
|
8815
|
+
description: "Include response body."
|
|
8458
8816
|
},
|
|
8459
8817
|
durationMs: {
|
|
8460
8818
|
type: "number",
|
|
8461
|
-
description: "Capture
|
|
8819
|
+
description: "Capture duration in milliseconds."
|
|
8462
8820
|
},
|
|
8463
8821
|
wake: {
|
|
8464
8822
|
type: "boolean",
|
|
8465
|
-
description: "
|
|
8823
|
+
description: "Wake worker before capture."
|
|
8466
8824
|
}
|
|
8467
8825
|
},
|
|
8468
8826
|
required: [],
|
|
@@ -8471,24 +8829,24 @@ var MANIFEST = [
|
|
|
8471
8829
|
},
|
|
8472
8830
|
{
|
|
8473
8831
|
name: "performance_start_trace",
|
|
8474
|
-
description: "
|
|
8832
|
+
description: "Start an in-process trace; stop it from the same process.",
|
|
8475
8833
|
inputSchema: {
|
|
8476
8834
|
type: "object",
|
|
8477
8835
|
properties: {
|
|
8478
8836
|
lease: {
|
|
8479
8837
|
type: "string",
|
|
8480
|
-
description: "Lease token
|
|
8838
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8481
8839
|
},
|
|
8482
8840
|
target: {
|
|
8483
8841
|
type: "string",
|
|
8484
|
-
description: "Page selector
|
|
8842
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8485
8843
|
},
|
|
8486
8844
|
categories: {
|
|
8487
8845
|
type: "array",
|
|
8488
8846
|
items: {
|
|
8489
8847
|
type: "string"
|
|
8490
8848
|
},
|
|
8491
|
-
description: "Trace categories
|
|
8849
|
+
description: "Trace categories."
|
|
8492
8850
|
}
|
|
8493
8851
|
},
|
|
8494
8852
|
required: [],
|
|
@@ -8497,17 +8855,17 @@ var MANIFEST = [
|
|
|
8497
8855
|
},
|
|
8498
8856
|
{
|
|
8499
8857
|
name: "performance_stop_trace",
|
|
8500
|
-
description: "
|
|
8858
|
+
description: "Stop the in-process trace and write JSON; a live trace is required.",
|
|
8501
8859
|
inputSchema: {
|
|
8502
8860
|
type: "object",
|
|
8503
8861
|
properties: {
|
|
8504
8862
|
lease: {
|
|
8505
8863
|
type: "string",
|
|
8506
|
-
description: "Lease token
|
|
8864
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8507
8865
|
},
|
|
8508
8866
|
target: {
|
|
8509
8867
|
type: "string",
|
|
8510
|
-
description: "Page selector
|
|
8868
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8511
8869
|
}
|
|
8512
8870
|
},
|
|
8513
8871
|
required: [],
|
|
@@ -8516,17 +8874,17 @@ var MANIFEST = [
|
|
|
8516
8874
|
},
|
|
8517
8875
|
{
|
|
8518
8876
|
name: "performance_analyze_insight",
|
|
8519
|
-
description: "
|
|
8877
|
+
description: "Analyze a trace JSON file for key performance metrics; tracePath is required.",
|
|
8520
8878
|
inputSchema: {
|
|
8521
8879
|
type: "object",
|
|
8522
8880
|
properties: {
|
|
8523
8881
|
lease: {
|
|
8524
8882
|
type: "string",
|
|
8525
|
-
description: "Lease token
|
|
8883
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8526
8884
|
},
|
|
8527
8885
|
tracePath: {
|
|
8528
8886
|
type: "string",
|
|
8529
|
-
description: "
|
|
8887
|
+
description: "Trace JSON file path."
|
|
8530
8888
|
}
|
|
8531
8889
|
},
|
|
8532
8890
|
required: [],
|
|
@@ -8535,36 +8893,36 @@ var MANIFEST = [
|
|
|
8535
8893
|
},
|
|
8536
8894
|
{
|
|
8537
8895
|
name: "performance_trace",
|
|
8538
|
-
description: "
|
|
8896
|
+
description: "Run a one-shot trace with optional navigation and write JSON; durationMs controls capture time.",
|
|
8539
8897
|
inputSchema: {
|
|
8540
8898
|
type: "object",
|
|
8541
8899
|
properties: {
|
|
8542
8900
|
lease: {
|
|
8543
8901
|
type: "string",
|
|
8544
|
-
description: "Lease token
|
|
8902
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8545
8903
|
},
|
|
8546
8904
|
target: {
|
|
8547
8905
|
type: "string",
|
|
8548
|
-
description: "Page selector
|
|
8906
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8549
8907
|
},
|
|
8550
8908
|
durationMs: {
|
|
8551
8909
|
type: "number",
|
|
8552
|
-
description: "
|
|
8910
|
+
description: "Capture duration in milliseconds."
|
|
8553
8911
|
},
|
|
8554
8912
|
reload: {
|
|
8555
8913
|
type: "boolean",
|
|
8556
|
-
description: "Reload
|
|
8914
|
+
description: "Reload before capture."
|
|
8557
8915
|
},
|
|
8558
8916
|
navigateTo: {
|
|
8559
8917
|
type: "string",
|
|
8560
|
-
description: "
|
|
8918
|
+
description: "Navigation URL."
|
|
8561
8919
|
},
|
|
8562
8920
|
categories: {
|
|
8563
8921
|
type: "array",
|
|
8564
8922
|
items: {
|
|
8565
8923
|
type: "string"
|
|
8566
8924
|
},
|
|
8567
|
-
description: "Trace categories
|
|
8925
|
+
description: "Trace categories."
|
|
8568
8926
|
}
|
|
8569
8927
|
},
|
|
8570
8928
|
required: [],
|
|
@@ -8573,17 +8931,17 @@ var MANIFEST = [
|
|
|
8573
8931
|
},
|
|
8574
8932
|
{
|
|
8575
8933
|
name: "start_screen_recording",
|
|
8576
|
-
description: "
|
|
8934
|
+
description: "Start a tab screen recording; stop it from the same process.",
|
|
8577
8935
|
inputSchema: {
|
|
8578
8936
|
type: "object",
|
|
8579
8937
|
properties: {
|
|
8580
8938
|
lease: {
|
|
8581
8939
|
type: "string",
|
|
8582
|
-
description: "Lease token
|
|
8940
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8583
8941
|
},
|
|
8584
8942
|
target: {
|
|
8585
8943
|
type: "string",
|
|
8586
|
-
description: "Page selector
|
|
8944
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8587
8945
|
},
|
|
8588
8946
|
format: {
|
|
8589
8947
|
type: "string",
|
|
@@ -8591,27 +8949,27 @@ var MANIFEST = [
|
|
|
8591
8949
|
"jpeg",
|
|
8592
8950
|
"png"
|
|
8593
8951
|
],
|
|
8594
|
-
description: "
|
|
8952
|
+
description: "Image/frame format."
|
|
8595
8953
|
},
|
|
8596
8954
|
quality: {
|
|
8597
8955
|
type: "number",
|
|
8598
|
-
description: "JPEG
|
|
8956
|
+
description: "JPEG quality 0-100."
|
|
8599
8957
|
},
|
|
8600
8958
|
maxWidth: {
|
|
8601
8959
|
type: "number",
|
|
8602
|
-
description: "
|
|
8960
|
+
description: "Maximum frame width."
|
|
8603
8961
|
},
|
|
8604
8962
|
maxHeight: {
|
|
8605
8963
|
type: "number",
|
|
8606
|
-
description: "
|
|
8964
|
+
description: "Maximum frame height."
|
|
8607
8965
|
},
|
|
8608
8966
|
everyNthFrame: {
|
|
8609
8967
|
type: "number",
|
|
8610
|
-
description: "Capture
|
|
8968
|
+
description: "Capture every Nth frame."
|
|
8611
8969
|
},
|
|
8612
8970
|
bringToFront: {
|
|
8613
8971
|
type: "boolean",
|
|
8614
|
-
description: "Activate
|
|
8972
|
+
description: "Activate tab before recording."
|
|
8615
8973
|
}
|
|
8616
8974
|
},
|
|
8617
8975
|
required: [],
|
|
@@ -8620,21 +8978,21 @@ var MANIFEST = [
|
|
|
8620
8978
|
},
|
|
8621
8979
|
{
|
|
8622
8980
|
name: "stop_screen_recording",
|
|
8623
|
-
description: "
|
|
8981
|
+
description: "Stop a screen recording and encode MP4; target is required when multiple recordings exist.",
|
|
8624
8982
|
inputSchema: {
|
|
8625
8983
|
type: "object",
|
|
8626
8984
|
properties: {
|
|
8627
8985
|
lease: {
|
|
8628
8986
|
type: "string",
|
|
8629
|
-
description: "Lease token
|
|
8987
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8630
8988
|
},
|
|
8631
8989
|
target: {
|
|
8632
8990
|
type: "string",
|
|
8633
|
-
description: "
|
|
8991
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8634
8992
|
},
|
|
8635
8993
|
savePath: {
|
|
8636
8994
|
type: "string",
|
|
8637
|
-
description: "
|
|
8995
|
+
description: "Output file path."
|
|
8638
8996
|
}
|
|
8639
8997
|
},
|
|
8640
8998
|
required: [],
|
|
@@ -8643,21 +9001,21 @@ var MANIFEST = [
|
|
|
8643
9001
|
},
|
|
8644
9002
|
{
|
|
8645
9003
|
name: "take_heapsnapshot",
|
|
8646
|
-
description: "
|
|
9004
|
+
description: "Capture a V8 heap snapshot to JSON; the snapshot is not parsed.",
|
|
8647
9005
|
inputSchema: {
|
|
8648
9006
|
type: "object",
|
|
8649
9007
|
properties: {
|
|
8650
9008
|
lease: {
|
|
8651
9009
|
type: "string",
|
|
8652
|
-
description: "Lease token
|
|
9010
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8653
9011
|
},
|
|
8654
9012
|
target: {
|
|
8655
9013
|
type: "string",
|
|
8656
|
-
description: "Page selector
|
|
9014
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8657
9015
|
},
|
|
8658
9016
|
savePath: {
|
|
8659
9017
|
type: "string",
|
|
8660
|
-
description: "
|
|
9018
|
+
description: "Output file path."
|
|
8661
9019
|
}
|
|
8662
9020
|
},
|
|
8663
9021
|
required: [],
|
|
@@ -8666,28 +9024,28 @@ var MANIFEST = [
|
|
|
8666
9024
|
},
|
|
8667
9025
|
{
|
|
8668
9026
|
name: "lighthouse_audit",
|
|
8669
|
-
description: "
|
|
9027
|
+
description: "Run Lighthouse against a URL in its own tab; it does not audit a user tab.",
|
|
8670
9028
|
inputSchema: {
|
|
8671
9029
|
type: "object",
|
|
8672
9030
|
properties: {
|
|
8673
9031
|
lease: {
|
|
8674
9032
|
type: "string",
|
|
8675
|
-
description: "Lease token
|
|
9033
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8676
9034
|
},
|
|
8677
9035
|
url: {
|
|
8678
9036
|
type: "string",
|
|
8679
|
-
description: "
|
|
9037
|
+
description: "URL value."
|
|
8680
9038
|
},
|
|
8681
9039
|
categories: {
|
|
8682
9040
|
type: "array",
|
|
8683
9041
|
items: {
|
|
8684
9042
|
type: "string"
|
|
8685
9043
|
},
|
|
8686
|
-
description:
|
|
9044
|
+
description: "Lighthouse categories to run (--only-categories)."
|
|
8687
9045
|
},
|
|
8688
9046
|
savePath: {
|
|
8689
9047
|
type: "string",
|
|
8690
|
-
description: "
|
|
9048
|
+
description: "Output file path."
|
|
8691
9049
|
},
|
|
8692
9050
|
formFactor: {
|
|
8693
9051
|
type: "string",
|
|
@@ -8695,11 +9053,11 @@ var MANIFEST = [
|
|
|
8695
9053
|
"desktop",
|
|
8696
9054
|
"mobile"
|
|
8697
9055
|
],
|
|
8698
|
-
description:
|
|
9056
|
+
description: "Lighthouse form factor."
|
|
8699
9057
|
},
|
|
8700
9058
|
timeoutMs: {
|
|
8701
9059
|
type: "number",
|
|
8702
|
-
description: "
|
|
9060
|
+
description: "Timeout in milliseconds."
|
|
8703
9061
|
}
|
|
8704
9062
|
},
|
|
8705
9063
|
required: [
|
|
@@ -8710,21 +9068,21 @@ var MANIFEST = [
|
|
|
8710
9068
|
},
|
|
8711
9069
|
{
|
|
8712
9070
|
name: "mock_request",
|
|
8713
|
-
description: "Register a
|
|
9071
|
+
description: "Register a persistent request mock; urlPattern is required.",
|
|
8714
9072
|
inputSchema: {
|
|
8715
9073
|
type: "object",
|
|
8716
9074
|
properties: {
|
|
8717
9075
|
lease: {
|
|
8718
9076
|
type: "string",
|
|
8719
|
-
description: "Lease token
|
|
9077
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8720
9078
|
},
|
|
8721
9079
|
target: {
|
|
8722
9080
|
type: "string",
|
|
8723
|
-
description: "
|
|
9081
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8724
9082
|
},
|
|
8725
9083
|
urlPattern: {
|
|
8726
9084
|
type: "string",
|
|
8727
|
-
description:
|
|
9085
|
+
description: "URL glob (*, ?; \\ escapes)."
|
|
8728
9086
|
},
|
|
8729
9087
|
action: {
|
|
8730
9088
|
type: "string",
|
|
@@ -8737,39 +9095,39 @@ var MANIFEST = [
|
|
|
8737
9095
|
},
|
|
8738
9096
|
status: {
|
|
8739
9097
|
type: "number",
|
|
8740
|
-
description: "
|
|
9098
|
+
description: "Mock HTTP status."
|
|
8741
9099
|
},
|
|
8742
9100
|
body: {
|
|
8743
9101
|
type: "string",
|
|
8744
|
-
description: "
|
|
9102
|
+
description: "Mock response body."
|
|
8745
9103
|
},
|
|
8746
9104
|
contentType: {
|
|
8747
9105
|
type: "string",
|
|
8748
|
-
description:
|
|
9106
|
+
description: "Response Content-Type."
|
|
8749
9107
|
},
|
|
8750
9108
|
headers: {
|
|
8751
9109
|
type: "object",
|
|
8752
|
-
description:
|
|
9110
|
+
description: "Extra response headers."
|
|
8753
9111
|
},
|
|
8754
9112
|
errorReason: {
|
|
8755
9113
|
type: "string",
|
|
8756
|
-
description:
|
|
9114
|
+
description: "CDP Network.ErrorReason, e.g. Failed|BlockedByClient|ConnectionRefused|TimedOut."
|
|
8757
9115
|
},
|
|
8758
9116
|
method: {
|
|
8759
9117
|
type: "string",
|
|
8760
|
-
description:
|
|
9118
|
+
description: "HTTP method."
|
|
8761
9119
|
},
|
|
8762
9120
|
delayMs: {
|
|
8763
9121
|
type: "number",
|
|
8764
|
-
description: "
|
|
9122
|
+
description: "Artificial delay in milliseconds."
|
|
8765
9123
|
},
|
|
8766
9124
|
failRate: {
|
|
8767
9125
|
type: "number",
|
|
8768
|
-
description: "
|
|
9126
|
+
description: "Failure probability 0..1."
|
|
8769
9127
|
},
|
|
8770
9128
|
reload: {
|
|
8771
9129
|
type: "boolean",
|
|
8772
|
-
description: "Reload
|
|
9130
|
+
description: "Reload before capture."
|
|
8773
9131
|
}
|
|
8774
9132
|
},
|
|
8775
9133
|
required: [
|
|
@@ -8780,13 +9138,13 @@ var MANIFEST = [
|
|
|
8780
9138
|
},
|
|
8781
9139
|
{
|
|
8782
9140
|
name: "list_mocks",
|
|
8783
|
-
description: "List active
|
|
9141
|
+
description: "List active request-mocking sessions and hit counts.",
|
|
8784
9142
|
inputSchema: {
|
|
8785
9143
|
type: "object",
|
|
8786
9144
|
properties: {
|
|
8787
9145
|
lease: {
|
|
8788
9146
|
type: "string",
|
|
8789
|
-
description: "Lease token
|
|
9147
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8790
9148
|
},
|
|
8791
9149
|
target: {
|
|
8792
9150
|
type: "string",
|
|
@@ -8799,17 +9157,17 @@ var MANIFEST = [
|
|
|
8799
9157
|
},
|
|
8800
9158
|
{
|
|
8801
9159
|
name: "clear_mocks",
|
|
8802
|
-
description: "
|
|
9160
|
+
description: "Clear the selected or all request-mocking sessions.",
|
|
8803
9161
|
inputSchema: {
|
|
8804
9162
|
type: "object",
|
|
8805
9163
|
properties: {
|
|
8806
9164
|
lease: {
|
|
8807
9165
|
type: "string",
|
|
8808
|
-
description: "Lease token
|
|
9166
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8809
9167
|
},
|
|
8810
9168
|
target: {
|
|
8811
9169
|
type: "string",
|
|
8812
|
-
description: "
|
|
9170
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8813
9171
|
},
|
|
8814
9172
|
all: {
|
|
8815
9173
|
type: "boolean",
|
|
@@ -8822,29 +9180,29 @@ var MANIFEST = [
|
|
|
8822
9180
|
},
|
|
8823
9181
|
{
|
|
8824
9182
|
name: "claim_page",
|
|
8825
|
-
description: "
|
|
9183
|
+
description: "Claim an existing tab or open a fresh one; CLI use is refused.",
|
|
8826
9184
|
inputSchema: {
|
|
8827
9185
|
type: "object",
|
|
8828
9186
|
properties: {
|
|
8829
9187
|
target: {
|
|
8830
9188
|
type: "string",
|
|
8831
|
-
description: "
|
|
9189
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8832
9190
|
},
|
|
8833
9191
|
targetId: {
|
|
8834
9192
|
type: "string",
|
|
8835
|
-
description: "Exact target
|
|
9193
|
+
description: "Exact target ID."
|
|
8836
9194
|
},
|
|
8837
9195
|
url: {
|
|
8838
9196
|
type: "string",
|
|
8839
|
-
description: "
|
|
9197
|
+
description: "URL value."
|
|
8840
9198
|
},
|
|
8841
9199
|
label: {
|
|
8842
9200
|
type: "string",
|
|
8843
|
-
description: "Agent
|
|
9201
|
+
description: "Agent lease label."
|
|
8844
9202
|
},
|
|
8845
9203
|
ttlMs: {
|
|
8846
9204
|
type: "number",
|
|
8847
|
-
description: "
|
|
9205
|
+
description: "Lease TTL in milliseconds."
|
|
8848
9206
|
}
|
|
8849
9207
|
},
|
|
8850
9208
|
required: [],
|
|
@@ -8853,21 +9211,21 @@ var MANIFEST = [
|
|
|
8853
9211
|
},
|
|
8854
9212
|
{
|
|
8855
9213
|
name: "release_page",
|
|
8856
|
-
description: "
|
|
9214
|
+
description: "Release a page lease and optionally close its tab; provide lease or target.",
|
|
8857
9215
|
inputSchema: {
|
|
8858
9216
|
type: "object",
|
|
8859
9217
|
properties: {
|
|
8860
9218
|
lease: {
|
|
8861
9219
|
type: "string",
|
|
8862
|
-
description: "
|
|
9220
|
+
description: "Lease token; omit for a tab this process already holds. See server instructions."
|
|
8863
9221
|
},
|
|
8864
9222
|
target: {
|
|
8865
9223
|
type: "string",
|
|
8866
|
-
description: "
|
|
9224
|
+
description: "Page selector (index:/url:/title:/label:/targetId, default active); grammar in server instructions."
|
|
8867
9225
|
},
|
|
8868
9226
|
close: {
|
|
8869
9227
|
type: "boolean",
|
|
8870
|
-
description: "
|
|
9228
|
+
description: "Override close behavior."
|
|
8871
9229
|
}
|
|
8872
9230
|
},
|
|
8873
9231
|
required: [],
|
|
@@ -8876,7 +9234,7 @@ var MANIFEST = [
|
|
|
8876
9234
|
},
|
|
8877
9235
|
{
|
|
8878
9236
|
name: "list_leases",
|
|
8879
|
-
description: "
|
|
9237
|
+
description: "List active leases for diagnosis without exposing lease tokens.",
|
|
8880
9238
|
inputSchema: {
|
|
8881
9239
|
type: "object",
|
|
8882
9240
|
properties: {},
|
|
@@ -8886,6 +9244,566 @@ var MANIFEST = [
|
|
|
8886
9244
|
}
|
|
8887
9245
|
];
|
|
8888
9246
|
|
|
9247
|
+
// src/install/wizard.ts
|
|
9248
|
+
import { createInterface } from "node:readline";
|
|
9249
|
+
import { homedir as homedir3 } from "node:os";
|
|
9250
|
+
import { join as join14 } from "node:path";
|
|
9251
|
+
|
|
9252
|
+
// src/install/browser.ts
|
|
9253
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
9254
|
+
import { mkdir as mkdir13, readFile as readFile9, writeFile as writeFile10 } from "node:fs/promises";
|
|
9255
|
+
import { homedir } from "node:os";
|
|
9256
|
+
import { delimiter, dirname as dirname3, join as join12 } from "node:path";
|
|
9257
|
+
var CANDIDATE_BUILDERS = {
|
|
9258
|
+
chrome: () => [
|
|
9259
|
+
process.env.CHROME_BIN,
|
|
9260
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
9261
|
+
"google-chrome",
|
|
9262
|
+
"google-chrome-stable",
|
|
9263
|
+
"chromium"
|
|
9264
|
+
],
|
|
9265
|
+
arc: () => [process.env.ARC_BIN, "/Applications/Arc.app/Contents/MacOS/Arc", "arc"],
|
|
9266
|
+
firefox: () => [
|
|
9267
|
+
process.env.FIREFOX_BIN,
|
|
9268
|
+
"/Applications/Firefox.app/Contents/MacOS/firefox",
|
|
9269
|
+
"firefox",
|
|
9270
|
+
"/usr/bin/firefox"
|
|
9271
|
+
]
|
|
9272
|
+
};
|
|
9273
|
+
function existsOnPath(cmd) {
|
|
9274
|
+
const pathEnv = process.env.PATH;
|
|
9275
|
+
if (!pathEnv)
|
|
9276
|
+
return false;
|
|
9277
|
+
for (const dir of pathEnv.split(delimiter)) {
|
|
9278
|
+
if (!dir)
|
|
9279
|
+
continue;
|
|
9280
|
+
if (existsSync2(join12(dir, cmd)))
|
|
9281
|
+
return true;
|
|
9282
|
+
}
|
|
9283
|
+
return false;
|
|
9284
|
+
}
|
|
9285
|
+
function resolveCandidate(candidates) {
|
|
9286
|
+
let lastDefined = "";
|
|
9287
|
+
for (const c of candidates) {
|
|
9288
|
+
if (!c)
|
|
9289
|
+
continue;
|
|
9290
|
+
lastDefined = c;
|
|
9291
|
+
if (c.startsWith("/")) {
|
|
9292
|
+
if (existsSync2(c))
|
|
9293
|
+
return { binary: c, found: true };
|
|
9294
|
+
continue;
|
|
9295
|
+
}
|
|
9296
|
+
if (existsOnPath(c))
|
|
9297
|
+
return { binary: c, found: true };
|
|
9298
|
+
}
|
|
9299
|
+
return { binary: lastDefined, found: false };
|
|
9300
|
+
}
|
|
9301
|
+
function detectBrowser(choice) {
|
|
9302
|
+
const { binary, found } = resolveCandidate(CANDIDATE_BUILDERS[choice]());
|
|
9303
|
+
return { choice, binary, found };
|
|
9304
|
+
}
|
|
9305
|
+
function defaultProfileDir(choice) {
|
|
9306
|
+
return `$HOME/.cdp-toolkit/${choice}-profile`;
|
|
9307
|
+
}
|
|
9308
|
+
function defaultAliasName(choice) {
|
|
9309
|
+
return `cdp-${choice}`;
|
|
9310
|
+
}
|
|
9311
|
+
function browserLaunchArgs(o) {
|
|
9312
|
+
const profileDir = o.profileDir ?? defaultProfileDir(o.choice);
|
|
9313
|
+
if (o.choice === "firefox") {
|
|
9314
|
+
return ["--remote-debugging-port", String(o.port), "--marionette", "--no-remote", "--profile", profileDir];
|
|
9315
|
+
}
|
|
9316
|
+
return [`--remote-debugging-port=${o.port}`, `--user-data-dir=${profileDir}`];
|
|
9317
|
+
}
|
|
9318
|
+
function shellQuoteIfSpaced(token) {
|
|
9319
|
+
return /\s/.test(token) ? `"${token}"` : token;
|
|
9320
|
+
}
|
|
9321
|
+
function aliasLine(o) {
|
|
9322
|
+
const name = o.aliasName ?? defaultAliasName(o.choice);
|
|
9323
|
+
const { binary } = detectBrowser(o.choice);
|
|
9324
|
+
const parts = [shellQuoteIfSpaced(binary), ...browserLaunchArgs(o)];
|
|
9325
|
+
return `alias ${name}='${parts.join(" ")}'`;
|
|
9326
|
+
}
|
|
9327
|
+
function detectShellRc() {
|
|
9328
|
+
const shell = process.env.SHELL ?? "";
|
|
9329
|
+
if (shell.endsWith("zsh"))
|
|
9330
|
+
return join12(homedir(), ".zshrc");
|
|
9331
|
+
if (shell.endsWith("bash"))
|
|
9332
|
+
return join12(homedir(), ".bashrc");
|
|
9333
|
+
return join12(homedir(), process.platform === "darwin" ? ".zshrc" : ".bashrc");
|
|
9334
|
+
}
|
|
9335
|
+
var MARKER_START = "# >>> cdp-toolkit alias >>>";
|
|
9336
|
+
var MARKER_END = "# <<< cdp-toolkit alias <<<";
|
|
9337
|
+
function ensureTrailingNewline(s) {
|
|
9338
|
+
return s.endsWith(`
|
|
9339
|
+
`) ? s : `${s}
|
|
9340
|
+
`;
|
|
9341
|
+
}
|
|
9342
|
+
async function appendAliasToRc(rcPath, aliasBlockBody) {
|
|
9343
|
+
let existing = "";
|
|
9344
|
+
try {
|
|
9345
|
+
existing = await readFile9(rcPath, "utf8");
|
|
9346
|
+
} catch (err) {
|
|
9347
|
+
if (err.code !== "ENOENT")
|
|
9348
|
+
throw err;
|
|
9349
|
+
}
|
|
9350
|
+
const block = `${MARKER_START}
|
|
9351
|
+
${aliasBlockBody}
|
|
9352
|
+
${MARKER_END}`;
|
|
9353
|
+
const startIdx = existing.indexOf(MARKER_START);
|
|
9354
|
+
const endIdx = existing.indexOf(MARKER_END);
|
|
9355
|
+
if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {
|
|
9356
|
+
const endOfEndLine = existing.indexOf(`
|
|
9357
|
+
`, endIdx);
|
|
9358
|
+
const before = existing.slice(0, startIdx);
|
|
9359
|
+
const after = endOfEndLine === -1 ? "" : existing.slice(endOfEndLine + 1);
|
|
9360
|
+
const existingBlock = existing.slice(startIdx, endOfEndLine === -1 ? existing.length : endOfEndLine);
|
|
9361
|
+
if (existingBlock === block) {
|
|
9362
|
+
return { rcPath, action: "unchanged" };
|
|
9363
|
+
}
|
|
9364
|
+
const next2 = ensureTrailingNewline(`${before}${block}
|
|
9365
|
+
${after}`);
|
|
9366
|
+
await writeFile10(rcPath, next2, "utf8");
|
|
9367
|
+
return { rcPath, action: "replaced-block" };
|
|
9368
|
+
}
|
|
9369
|
+
await mkdir13(dirname3(rcPath), { recursive: true });
|
|
9370
|
+
const sep = existing.length === 0 || existing.endsWith(`
|
|
9371
|
+
`) ? "" : `
|
|
9372
|
+
`;
|
|
9373
|
+
const next = `${existing}${sep}${block}
|
|
9374
|
+
`;
|
|
9375
|
+
await writeFile10(rcPath, next, "utf8");
|
|
9376
|
+
return { rcPath, action: "created-block" };
|
|
9377
|
+
}
|
|
9378
|
+
|
|
9379
|
+
// src/install/harness.ts
|
|
9380
|
+
import { spawnSync } from "node:child_process";
|
|
9381
|
+
import { mkdir as mkdir14, readFile as readFile10, writeFile as writeFile11 } from "node:fs/promises";
|
|
9382
|
+
import { homedir as homedir2 } from "node:os";
|
|
9383
|
+
import { dirname as dirname4, join as join13 } from "node:path";
|
|
9384
|
+
async function installMcpServer(harness, name, cfg, opts = {}) {
|
|
9385
|
+
switch (harness) {
|
|
9386
|
+
case "claude":
|
|
9387
|
+
return installClaude(name, cfg, opts);
|
|
9388
|
+
case "codex":
|
|
9389
|
+
return installCodex(name, cfg);
|
|
9390
|
+
case "opencode":
|
|
9391
|
+
return installOpencode(name, cfg);
|
|
9392
|
+
default: {
|
|
9393
|
+
const exhaustive = harness;
|
|
9394
|
+
throw new Error(`unknown harness: ${String(exhaustive)}`);
|
|
9395
|
+
}
|
|
9396
|
+
}
|
|
9397
|
+
}
|
|
9398
|
+
async function installClaude(name, cfg, opts) {
|
|
9399
|
+
const path = opts.configPath ?? join13(opts.homeDir ?? homedir2(), ".claude.json");
|
|
9400
|
+
let root;
|
|
9401
|
+
let fileExisted;
|
|
9402
|
+
try {
|
|
9403
|
+
const text = await readFile10(path, "utf8");
|
|
9404
|
+
const parsed = JSON.parse(text);
|
|
9405
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
9406
|
+
throw new Error(`${path} does not contain a JSON object at its top level`);
|
|
9407
|
+
}
|
|
9408
|
+
root = parsed;
|
|
9409
|
+
fileExisted = true;
|
|
9410
|
+
} catch (err) {
|
|
9411
|
+
if (err.code === "ENOENT") {
|
|
9412
|
+
root = {};
|
|
9413
|
+
fileExisted = false;
|
|
9414
|
+
} else {
|
|
9415
|
+
throw err;
|
|
9416
|
+
}
|
|
9417
|
+
}
|
|
9418
|
+
const rawServers = root.mcpServers;
|
|
9419
|
+
const mcpServers = typeof rawServers === "object" && rawServers !== null && !Array.isArray(rawServers) ? rawServers : {};
|
|
9420
|
+
root.mcpServers = mcpServers;
|
|
9421
|
+
const entry = { command: cfg.command, args: cfg.args };
|
|
9422
|
+
if (Object.keys(cfg.env).length > 0)
|
|
9423
|
+
entry.env = cfg.env;
|
|
9424
|
+
const prior = mcpServers[name];
|
|
9425
|
+
const action = prior === undefined ? "added" : canonicalJson(prior) === canonicalJson(entry) ? "unchanged" : "updated";
|
|
9426
|
+
mcpServers[name] = entry;
|
|
9427
|
+
if (action === "unchanged") {
|
|
9428
|
+
return { harness: "claude", method: "file", path, action, detail: "no change needed" };
|
|
9429
|
+
}
|
|
9430
|
+
await mkdir14(dirname4(path), { recursive: true });
|
|
9431
|
+
await writeFile11(path, JSON.stringify(root, null, 2) + `
|
|
9432
|
+
`, "utf8");
|
|
9433
|
+
return {
|
|
9434
|
+
harness: "claude",
|
|
9435
|
+
method: "file",
|
|
9436
|
+
path,
|
|
9437
|
+
action,
|
|
9438
|
+
detail: fileExisted ? undefined : "created new config file"
|
|
9439
|
+
};
|
|
9440
|
+
}
|
|
9441
|
+
function canonicalJson(value) {
|
|
9442
|
+
return JSON.stringify(canonicalize(value));
|
|
9443
|
+
}
|
|
9444
|
+
function canonicalize(value) {
|
|
9445
|
+
if (Array.isArray(value))
|
|
9446
|
+
return value.map(canonicalize);
|
|
9447
|
+
if (value !== null && typeof value === "object") {
|
|
9448
|
+
const out = {};
|
|
9449
|
+
for (const key of Object.keys(value).sort()) {
|
|
9450
|
+
out[key] = canonicalize(value[key]);
|
|
9451
|
+
}
|
|
9452
|
+
return out;
|
|
9453
|
+
}
|
|
9454
|
+
return value;
|
|
9455
|
+
}
|
|
9456
|
+
function codexAddArgs(name, cfg) {
|
|
9457
|
+
const envArgs = Object.entries(cfg.env).flatMap(([k, v]) => ["--env", `${k}=${v}`]);
|
|
9458
|
+
return ["mcp", "add", name, ...envArgs, "--", cfg.command, ...cfg.args];
|
|
9459
|
+
}
|
|
9460
|
+
async function installCodex(name, cfg) {
|
|
9461
|
+
if (!isOnPath("codex")) {
|
|
9462
|
+
throw new Error("codex CLI not found on PATH — install Codex or pick a different harness");
|
|
9463
|
+
}
|
|
9464
|
+
const probe = spawnSync("codex", ["mcp", "get", name], { encoding: "utf8" });
|
|
9465
|
+
const exists = probe.status === 0;
|
|
9466
|
+
if (exists) {
|
|
9467
|
+
const removed = spawnSync("codex", ["mcp", "remove", name], { encoding: "utf8" });
|
|
9468
|
+
if (removed.status !== 0) {
|
|
9469
|
+
throw new Error(`codex mcp remove ${name} failed: ${(removed.stderr || removed.stdout || "").trim()}`);
|
|
9470
|
+
}
|
|
9471
|
+
}
|
|
9472
|
+
const addArgs = codexAddArgs(name, cfg);
|
|
9473
|
+
const added = spawnSync("codex", addArgs, { encoding: "utf8" });
|
|
9474
|
+
if (added.status !== 0) {
|
|
9475
|
+
throw new Error(`codex ${addArgs.join(" ")} failed: ${(added.stderr || added.stdout || "").trim()}`);
|
|
9476
|
+
}
|
|
9477
|
+
return {
|
|
9478
|
+
harness: "codex",
|
|
9479
|
+
method: "cli",
|
|
9480
|
+
action: exists ? "updated" : "added",
|
|
9481
|
+
detail: added.stdout?.trim() || undefined
|
|
9482
|
+
};
|
|
9483
|
+
}
|
|
9484
|
+
function opencodeAddArgs(name, cfg) {
|
|
9485
|
+
const envArgs = Object.entries(cfg.env).flatMap(([k, v]) => ["--env", `${k}=${v}`]);
|
|
9486
|
+
return ["mcp", "add", name, ...envArgs, "--", cfg.command, ...cfg.args];
|
|
9487
|
+
}
|
|
9488
|
+
async function installOpencode(name, cfg) {
|
|
9489
|
+
if (!isOnPath("opencode")) {
|
|
9490
|
+
throw new Error("opencode CLI not found on PATH — install OpenCode or pick a different harness");
|
|
9491
|
+
}
|
|
9492
|
+
const addArgs = opencodeAddArgs(name, cfg);
|
|
9493
|
+
const added = spawnSync("opencode", addArgs, { encoding: "utf8" });
|
|
9494
|
+
if (added.status !== 0) {
|
|
9495
|
+
throw new Error(`opencode ${addArgs.join(" ")} failed: ${(added.stderr || added.stdout || "").trim()}`);
|
|
9496
|
+
}
|
|
9497
|
+
return {
|
|
9498
|
+
harness: "opencode",
|
|
9499
|
+
method: "cli",
|
|
9500
|
+
action: "added",
|
|
9501
|
+
detail: added.stdout?.trim() || undefined
|
|
9502
|
+
};
|
|
9503
|
+
}
|
|
9504
|
+
function isOnPath(bin) {
|
|
9505
|
+
const finder = process.platform === "win32" ? "where" : "which";
|
|
9506
|
+
const result = spawnSync(finder, [bin], { encoding: "utf8" });
|
|
9507
|
+
return result.status === 0;
|
|
9508
|
+
}
|
|
9509
|
+
|
|
9510
|
+
// src/install/wizard.ts
|
|
9511
|
+
var DEFAULT_NAME = "cdp-toolkit";
|
|
9512
|
+
var HARNESSES = ["claude", "codex", "opencode"];
|
|
9513
|
+
var BROWSERS = ["arc", "chrome", "firefox"];
|
|
9514
|
+
function defaultPortFor(browser) {
|
|
9515
|
+
return browser === "firefox" ? 9223 : 9222;
|
|
9516
|
+
}
|
|
9517
|
+
function parseHarness(v) {
|
|
9518
|
+
if (v === undefined)
|
|
9519
|
+
throw new Error("--harness requires a value: claude, codex, or opencode");
|
|
9520
|
+
if (HARNESSES.includes(v))
|
|
9521
|
+
return v;
|
|
9522
|
+
throw new Error(`--harness must be one of claude|codex|opencode (got '${v}')`);
|
|
9523
|
+
}
|
|
9524
|
+
function parseBrowserChoice(v) {
|
|
9525
|
+
if (v === undefined)
|
|
9526
|
+
throw new Error("--browser requires a value: arc, chrome, or firefox");
|
|
9527
|
+
if (BROWSERS.includes(v))
|
|
9528
|
+
return v;
|
|
9529
|
+
throw new Error(`--browser must be one of arc|chrome|firefox (got '${v}')`);
|
|
9530
|
+
}
|
|
9531
|
+
function parsePort(v) {
|
|
9532
|
+
if (v === undefined)
|
|
9533
|
+
throw new Error("--port requires a value (an integer 1-65535)");
|
|
9534
|
+
const n = Number(v);
|
|
9535
|
+
if (!Number.isInteger(n) || n < 1 || n > 65535) {
|
|
9536
|
+
throw new Error(`--port must be an integer 1-65535 (got '${v}')`);
|
|
9537
|
+
}
|
|
9538
|
+
return n;
|
|
9539
|
+
}
|
|
9540
|
+
function normalizeArgv(argv) {
|
|
9541
|
+
const out = [];
|
|
9542
|
+
for (const t of argv) {
|
|
9543
|
+
if (t.startsWith("--") && t.includes("=")) {
|
|
9544
|
+
const eq = t.indexOf("=");
|
|
9545
|
+
out.push(t.slice(0, eq), t.slice(eq + 1));
|
|
9546
|
+
} else {
|
|
9547
|
+
out.push(t);
|
|
9548
|
+
}
|
|
9549
|
+
}
|
|
9550
|
+
return out;
|
|
9551
|
+
}
|
|
9552
|
+
function parseInstallArgs(argv) {
|
|
9553
|
+
const tokens = normalizeArgv(argv);
|
|
9554
|
+
const out = { name: DEFAULT_NAME, alias: true };
|
|
9555
|
+
for (let i = 0;i < tokens.length; i++) {
|
|
9556
|
+
const t = tokens[i];
|
|
9557
|
+
switch (t) {
|
|
9558
|
+
case "--help":
|
|
9559
|
+
case "-h":
|
|
9560
|
+
out.help = true;
|
|
9561
|
+
break;
|
|
9562
|
+
case "--yes":
|
|
9563
|
+
case "-y":
|
|
9564
|
+
out.yes = true;
|
|
9565
|
+
break;
|
|
9566
|
+
case "--no-alias":
|
|
9567
|
+
out.alias = false;
|
|
9568
|
+
break;
|
|
9569
|
+
case "--alias":
|
|
9570
|
+
out.alias = true;
|
|
9571
|
+
break;
|
|
9572
|
+
case "--harness":
|
|
9573
|
+
out.harness = parseHarness(tokens[++i]);
|
|
9574
|
+
break;
|
|
9575
|
+
case "--browser":
|
|
9576
|
+
out.browser = parseBrowserChoice(tokens[++i]);
|
|
9577
|
+
break;
|
|
9578
|
+
case "--port":
|
|
9579
|
+
out.port = parsePort(tokens[++i]);
|
|
9580
|
+
break;
|
|
9581
|
+
case "--name": {
|
|
9582
|
+
const v = tokens[++i];
|
|
9583
|
+
if (v === undefined)
|
|
9584
|
+
throw new Error("--name requires a value");
|
|
9585
|
+
out.name = v;
|
|
9586
|
+
break;
|
|
9587
|
+
}
|
|
9588
|
+
case "--alias-name": {
|
|
9589
|
+
const v = tokens[++i];
|
|
9590
|
+
if (v === undefined)
|
|
9591
|
+
throw new Error("--alias-name requires a value");
|
|
9592
|
+
out.aliasName = v;
|
|
9593
|
+
break;
|
|
9594
|
+
}
|
|
9595
|
+
default:
|
|
9596
|
+
throw new Error(`cdp install: unknown option '${t}' (run \`cdp install --help\`)`);
|
|
9597
|
+
}
|
|
9598
|
+
}
|
|
9599
|
+
return out;
|
|
9600
|
+
}
|
|
9601
|
+
function composeServerConfig(browser, port) {
|
|
9602
|
+
const env = browser === "firefox" ? { CDP_BROWSER: "firefox", CDP_FIREFOX_ENDPOINT: String(port) } : { CDP_BASE: `http://127.0.0.1:${port}` };
|
|
9603
|
+
return { command: "npx", args: ["-y", "cdp-toolkit"], env };
|
|
9604
|
+
}
|
|
9605
|
+
function installHelpText() {
|
|
9606
|
+
return `cdp install — register the cdp-toolkit MCP server with your coding harness and add a
|
|
9607
|
+
browser-launch alias (with the remote-debugging port open) to your shell rc.
|
|
9608
|
+
|
|
9609
|
+
Usage:
|
|
9610
|
+
cdp install [--harness <claude|codex|opencode>] [--browser <arc|chrome|firefox>]
|
|
9611
|
+
[--port <n>] [--name <server-name>] [--alias-name <name>]
|
|
9612
|
+
[--no-alias] [--yes|-y] [--help|-h]
|
|
9613
|
+
|
|
9614
|
+
Options:
|
|
9615
|
+
--harness <h> Coding harness to register the MCP server with: claude, codex, opencode.
|
|
9616
|
+
--browser <b> Browser the alias launches: arc, chrome, firefox.
|
|
9617
|
+
--port <n> Remote-debugging port (1-65535). Default: 9222 (chrome/arc), 9223 (firefox).
|
|
9618
|
+
--name <name> MCP server name to register. Default: ${DEFAULT_NAME}.
|
|
9619
|
+
--alias-name <n> Shell alias name. Default: cdp-<browser> (e.g. cdp-firefox).
|
|
9620
|
+
--no-alias Register the MCP server only; skip writing the shell alias.
|
|
9621
|
+
--yes, -y Skip the confirmation prompt (proceed immediately).
|
|
9622
|
+
--help, -h Show this help.
|
|
9623
|
+
|
|
9624
|
+
Interactive: run \`cdp install\` in a terminal with no flags and it prompts for harness, browser,
|
|
9625
|
+
and port, then asks before writing anything.
|
|
9626
|
+
|
|
9627
|
+
Non-interactive (piped/CI): pass at least --harness and --browser (port defaults per browser); a
|
|
9628
|
+
missing required value fails fast with usage instead of hanging on stdin.`;
|
|
9629
|
+
}
|
|
9630
|
+
async function ask(question) {
|
|
9631
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
9632
|
+
try {
|
|
9633
|
+
return await new Promise((resolve) => rl.question(question, resolve));
|
|
9634
|
+
} finally {
|
|
9635
|
+
rl.close();
|
|
9636
|
+
}
|
|
9637
|
+
}
|
|
9638
|
+
async function promptMenu(label, options) {
|
|
9639
|
+
const lines = [label];
|
|
9640
|
+
options.forEach((o, i) => lines.push(` ${i + 1}) ${o}`));
|
|
9641
|
+
process.stdout.write(`${lines.join(`
|
|
9642
|
+
`)}
|
|
9643
|
+
`);
|
|
9644
|
+
for (;; ) {
|
|
9645
|
+
const ans = (await ask(`Enter 1-${options.length}: `)).trim();
|
|
9646
|
+
const n = Number(ans);
|
|
9647
|
+
if (Number.isInteger(n) && n >= 1 && n <= options.length)
|
|
9648
|
+
return options[n - 1];
|
|
9649
|
+
process.stdout.write(`Please enter a number between 1 and ${options.length}.
|
|
9650
|
+
`);
|
|
9651
|
+
}
|
|
9652
|
+
}
|
|
9653
|
+
async function promptPort(def) {
|
|
9654
|
+
for (;; ) {
|
|
9655
|
+
const ans = (await ask(`Remote-debugging port [${def}]: `)).trim();
|
|
9656
|
+
if (ans === "")
|
|
9657
|
+
return def;
|
|
9658
|
+
const n = Number(ans);
|
|
9659
|
+
if (Number.isInteger(n) && n >= 1 && n <= 65535)
|
|
9660
|
+
return n;
|
|
9661
|
+
process.stdout.write(`Please enter an integer between 1 and 65535.
|
|
9662
|
+
`);
|
|
9663
|
+
}
|
|
9664
|
+
}
|
|
9665
|
+
function harnessTargetDesc(harness, io) {
|
|
9666
|
+
if (harness === "claude") {
|
|
9667
|
+
return io.configPath ?? join14(io.homeDir ?? homedir3(), ".claude.json");
|
|
9668
|
+
}
|
|
9669
|
+
return `via \`${harness} mcp add\``;
|
|
9670
|
+
}
|
|
9671
|
+
function binEnvVar(browser) {
|
|
9672
|
+
return `${browser.toUpperCase()}_BIN`;
|
|
9673
|
+
}
|
|
9674
|
+
async function runInstaller(argv, io = {}) {
|
|
9675
|
+
const write = io.stdout ?? ((s) => void process.stdout.write(s));
|
|
9676
|
+
const writeErr = io.stderr ?? ((s) => void process.stderr.write(s));
|
|
9677
|
+
const isTTY = io.isTTY ?? Boolean(process.stdin.isTTY);
|
|
9678
|
+
let args;
|
|
9679
|
+
try {
|
|
9680
|
+
args = parseInstallArgs(argv);
|
|
9681
|
+
} catch (err) {
|
|
9682
|
+
writeErr(`${err.message}
|
|
9683
|
+
|
|
9684
|
+
`);
|
|
9685
|
+
writeErr(`${installHelpText()}
|
|
9686
|
+
`);
|
|
9687
|
+
return 1;
|
|
9688
|
+
}
|
|
9689
|
+
if (args.help) {
|
|
9690
|
+
write(`${installHelpText()}
|
|
9691
|
+
`);
|
|
9692
|
+
return 0;
|
|
9693
|
+
}
|
|
9694
|
+
let harness = args.harness;
|
|
9695
|
+
let browser = args.browser;
|
|
9696
|
+
let port = args.port;
|
|
9697
|
+
if (isTTY) {
|
|
9698
|
+
if (harness === undefined)
|
|
9699
|
+
harness = await promptMenu("Which coding harness?", HARNESSES);
|
|
9700
|
+
if (browser === undefined)
|
|
9701
|
+
browser = await promptMenu("Which browser?", BROWSERS);
|
|
9702
|
+
if (port === undefined)
|
|
9703
|
+
port = await promptPort(defaultPortFor(browser));
|
|
9704
|
+
} else {
|
|
9705
|
+
const missing = [];
|
|
9706
|
+
if (harness === undefined)
|
|
9707
|
+
missing.push("--harness");
|
|
9708
|
+
if (browser === undefined)
|
|
9709
|
+
missing.push("--browser");
|
|
9710
|
+
if (missing.length > 0) {
|
|
9711
|
+
writeErr(`cdp install: missing required option(s) ${missing.join(", ")} in non-interactive mode.
|
|
9712
|
+
`);
|
|
9713
|
+
writeErr("Run `cdp install` in a terminal to be prompted, or pass the option(s) explicitly.\n\n");
|
|
9714
|
+
writeErr(`${installHelpText()}
|
|
9715
|
+
`);
|
|
9716
|
+
return 1;
|
|
9717
|
+
}
|
|
9718
|
+
if (port === undefined)
|
|
9719
|
+
port = defaultPortFor(browser);
|
|
9720
|
+
}
|
|
9721
|
+
if (harness === undefined || browser === undefined || port === undefined) {
|
|
9722
|
+
writeErr(`cdp install: internal error resolving options
|
|
9723
|
+
`);
|
|
9724
|
+
return 1;
|
|
9725
|
+
}
|
|
9726
|
+
const name = args.name ?? DEFAULT_NAME;
|
|
9727
|
+
const writeAlias = args.alias !== false;
|
|
9728
|
+
const rcPath = io.rcPath ?? detectShellRc();
|
|
9729
|
+
const resolvedAliasName = args.aliasName ?? defaultAliasName(browser);
|
|
9730
|
+
const line = aliasLine({ choice: browser, port, aliasName: args.aliasName });
|
|
9731
|
+
if (!args.yes && isTTY) {
|
|
9732
|
+
const plan = [
|
|
9733
|
+
"",
|
|
9734
|
+
"About to:",
|
|
9735
|
+
` - Register MCP server "${name}" with ${harness} (${harnessTargetDesc(harness, io)})`,
|
|
9736
|
+
writeAlias ? ` - Append a shell alias to ${rcPath}:
|
|
9737
|
+
${line}` : " - (skipping shell alias: --no-alias)",
|
|
9738
|
+
""
|
|
9739
|
+
].join(`
|
|
9740
|
+
`);
|
|
9741
|
+
write(`${plan}
|
|
9742
|
+
`);
|
|
9743
|
+
const ans = (await ask("Proceed? [y/N] ")).trim();
|
|
9744
|
+
if (!/^y(es)?$/i.test(ans)) {
|
|
9745
|
+
write(`Aborted. Nothing was written.
|
|
9746
|
+
`);
|
|
9747
|
+
return 0;
|
|
9748
|
+
}
|
|
9749
|
+
}
|
|
9750
|
+
let harnessResult;
|
|
9751
|
+
try {
|
|
9752
|
+
harnessResult = await installMcpServer(harness, name, composeServerConfig(browser, port), {
|
|
9753
|
+
configPath: io.configPath,
|
|
9754
|
+
homeDir: io.homeDir
|
|
9755
|
+
});
|
|
9756
|
+
} catch (err) {
|
|
9757
|
+
writeErr(`cdp install: could not register the MCP server with ${harness}: ${err.message}
|
|
9758
|
+
`);
|
|
9759
|
+
return 1;
|
|
9760
|
+
}
|
|
9761
|
+
let rcResult;
|
|
9762
|
+
let browserFound = true;
|
|
9763
|
+
if (writeAlias) {
|
|
9764
|
+
rcResult = await appendAliasToRc(rcPath, line);
|
|
9765
|
+
browserFound = detectBrowser(browser).found;
|
|
9766
|
+
if (!browserFound) {
|
|
9767
|
+
writeErr(`
|
|
9768
|
+
Warning: could not find the ${browser} binary at its expected location. The alias was ` + `written anyway, but \`${resolvedAliasName}\` will not launch until the binary is found.
|
|
9769
|
+
` + ` Fix: set ${binEnvVar(browser)}=/path/to/${browser} and re-run \`cdp install\`, or edit the
|
|
9770
|
+
` + ` alias line in ${rcPath} to point at the real binary.
|
|
9771
|
+
`);
|
|
9772
|
+
}
|
|
9773
|
+
}
|
|
9774
|
+
const summary = [
|
|
9775
|
+
"",
|
|
9776
|
+
"cdp-toolkit install complete.",
|
|
9777
|
+
"",
|
|
9778
|
+
`Harness: ${harness}`,
|
|
9779
|
+
` server name: ${name}`,
|
|
9780
|
+
harnessResult.path ? ` config: ${harnessResult.path}` : ` registered: ${harnessTargetDesc(harness, io)}`,
|
|
9781
|
+
` method: ${harnessResult.method}`,
|
|
9782
|
+
` action: ${harnessResult.action}${harnessResult.detail ? ` (${harnessResult.detail})` : ""}`
|
|
9783
|
+
];
|
|
9784
|
+
if (writeAlias && rcResult) {
|
|
9785
|
+
summary.push("", `Browser alias: ${resolvedAliasName} -> ${rcResult.rcPath}`, ` action: ${rcResult.action}`, ` line: ${line}`);
|
|
9786
|
+
if (!browserFound)
|
|
9787
|
+
summary.push(` note: ${browser} binary not found yet (see warning above)`);
|
|
9788
|
+
} else {
|
|
9789
|
+
summary.push("", "Browser alias: skipped (--no-alias).");
|
|
9790
|
+
}
|
|
9791
|
+
summary.push("", "Next steps:");
|
|
9792
|
+
if (writeAlias && rcResult) {
|
|
9793
|
+
summary.push(` 1. Load the alias into your shell: source ${rcResult.rcPath} (or open a new terminal)`, ` 2. Launch the browser with the debug port open: ${resolvedAliasName}`, ` 3. Restart / reconnect ${harness} so it picks up the "${name}" MCP server.`);
|
|
9794
|
+
if (browser === "firefox") {
|
|
9795
|
+
summary.push("", "Firefox note: the alias includes --marionette, which cdp-toolkit needs for its orphan", "auto-recovery path — don't remove it.");
|
|
9796
|
+
}
|
|
9797
|
+
} else {
|
|
9798
|
+
summary.push(` 1. Restart / reconnect ${harness} so it picks up the "${name}" MCP server.`);
|
|
9799
|
+
}
|
|
9800
|
+
summary.push("");
|
|
9801
|
+
write(`${summary.join(`
|
|
9802
|
+
`)}
|
|
9803
|
+
`);
|
|
9804
|
+
return 0;
|
|
9805
|
+
}
|
|
9806
|
+
|
|
8889
9807
|
// src/cli.ts
|
|
8890
9808
|
var USAGE = `cdp-toolkit: raw single-target CDP, 29-tool chrome-devtools-mcp parity, plus a Firefox backend over WebDriver BiDi.
|
|
8891
9809
|
|
|
@@ -9034,6 +9952,9 @@ function printToolHelp(name) {
|
|
|
9034
9952
|
}
|
|
9035
9953
|
async function main() {
|
|
9036
9954
|
const rawArgv = process.argv.slice(2);
|
|
9955
|
+
if (rawArgv[0] === "install") {
|
|
9956
|
+
return await runInstaller(rawArgv.slice(1));
|
|
9957
|
+
}
|
|
9037
9958
|
const { kind: browser, endpoint } = resolveBackend(rawArgv);
|
|
9038
9959
|
const parsed = parseArgv(stripConnectFlag(stripBrowserFlag(rawArgv)));
|
|
9039
9960
|
if (parsed.help) {
|