@mearl/native-host 2.4.0 → 2.5.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/dist/agentbay-browser.d.ts +91 -0
- package/dist/browser-inventory.d.ts +2 -1
- package/dist/cdp-backend/cdp-session.d.ts +10 -4
- package/dist/cdp-backend/client.d.ts +8 -21
- package/dist/cdp-backend/cookie-transfer.d.ts +5 -0
- package/dist/index.js +731 -351
- package/dist/managed-browser.d.ts +6 -0
- package/package.json +9 -4
package/dist/index.js
CHANGED
|
@@ -46,7 +46,7 @@ function uninstallNativeHostArtifacts(options = {}, dependencies = {}) {
|
|
|
46
46
|
writeLine(line);
|
|
47
47
|
};
|
|
48
48
|
try {
|
|
49
|
-
const
|
|
49
|
+
const existsSync5 = dependencies.existsSync ?? fs11.existsSync;
|
|
50
50
|
const platform = dependencies.platform ?? process.platform;
|
|
51
51
|
const hostDir = dependencies.hostDir ?? resolveNativeHostDirectory({
|
|
52
52
|
env: dependencies.env,
|
|
@@ -62,7 +62,7 @@ function uninstallNativeHostArtifacts(options = {}, dependencies = {}) {
|
|
|
62
62
|
path12.join(hostDir, `${hostName}-launcher.${launcherExtension}`)
|
|
63
63
|
];
|
|
64
64
|
for (const artifact of artifacts) {
|
|
65
|
-
if (!
|
|
65
|
+
if (!existsSync5(artifact))
|
|
66
66
|
continue;
|
|
67
67
|
unlinkSync(artifact);
|
|
68
68
|
log2(`✅ Removed: ${artifact}`);
|
|
@@ -98,7 +98,7 @@ import fs12 from "node:fs";
|
|
|
98
98
|
import path13 from "node:path";
|
|
99
99
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
100
100
|
import { createRequire } from "node:module";
|
|
101
|
-
import { fileURLToPath as
|
|
101
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
102
102
|
function resolveHostDir() {
|
|
103
103
|
return resolveNativeHostDirectory();
|
|
104
104
|
}
|
|
@@ -306,7 +306,7 @@ var init_install = __esm({
|
|
|
306
306
|
"use strict";
|
|
307
307
|
init_nativeHost();
|
|
308
308
|
DEFAULT_EXTENSION_ID = "aoehhjnofngknnjefamjbplchbolghkm";
|
|
309
|
-
__filename =
|
|
309
|
+
__filename = fileURLToPath3(import.meta.url);
|
|
310
310
|
__dirname = path13.dirname(__filename);
|
|
311
311
|
ALL_MODES = ["skills", "mcp"];
|
|
312
312
|
}
|
|
@@ -315,17 +315,16 @@ var init_install = __esm({
|
|
|
315
315
|
// src/index.ts
|
|
316
316
|
import net from "node:net";
|
|
317
317
|
import fs13 from "node:fs";
|
|
318
|
-
import
|
|
318
|
+
import http4 from "node:http";
|
|
319
319
|
import os7 from "node:os";
|
|
320
320
|
import path14 from "node:path";
|
|
321
|
-
import { fileURLToPath as
|
|
321
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
322
322
|
|
|
323
323
|
// src/cdp-backend/cdp-session.ts
|
|
324
|
-
import
|
|
324
|
+
import http2 from "node:http";
|
|
325
325
|
|
|
326
326
|
// src/cdp-backend/client.ts
|
|
327
|
-
import
|
|
328
|
-
import crypto2 from "node:crypto";
|
|
327
|
+
import WebSocket from "ws";
|
|
329
328
|
var CdpChildSession = class {
|
|
330
329
|
constructor(parent, sessionId) {
|
|
331
330
|
this.parent = parent;
|
|
@@ -344,199 +343,89 @@ var CdpChildSession = class {
|
|
|
344
343
|
}
|
|
345
344
|
};
|
|
346
345
|
var CdpClient = class _CdpClient {
|
|
347
|
-
socket
|
|
348
|
-
|
|
346
|
+
constructor(socket) {
|
|
347
|
+
this.socket = socket;
|
|
348
|
+
socket.on("message", (data) => this.consumeMessage(data));
|
|
349
|
+
socket.on("close", () => this.handleClosed());
|
|
350
|
+
socket.on("error", () => this.handleClosed());
|
|
351
|
+
}
|
|
349
352
|
nextId = 1;
|
|
350
353
|
pending = /* @__PURE__ */ new Map();
|
|
351
354
|
eventHandlers = /* @__PURE__ */ new Map();
|
|
352
|
-
/** sessionId → method → callbacks (for multiplexed page sessions) */
|
|
353
355
|
sessionEventHandlers = /* @__PURE__ */ new Map();
|
|
354
356
|
_closed = false;
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
for (const [id, pending] of this.pending) {
|
|
364
|
-
clearTimeout(pending.timer);
|
|
365
|
-
pending.reject(new Error("CDP connection closed"));
|
|
366
|
-
this.pending.delete(id);
|
|
357
|
+
static connect(wsUrl) {
|
|
358
|
+
return new Promise((resolve2, reject) => {
|
|
359
|
+
let url2;
|
|
360
|
+
try {
|
|
361
|
+
url2 = new URL(wsUrl);
|
|
362
|
+
} catch {
|
|
363
|
+
reject(new Error("Invalid CDP WebSocket URL"));
|
|
364
|
+
return;
|
|
367
365
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
366
|
+
if (url2.protocol !== "ws:" && url2.protocol !== "wss:") {
|
|
367
|
+
reject(new Error(`Unsupported CDP WebSocket protocol: ${url2.protocol}`));
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const socket = new WebSocket(url2, {
|
|
371
|
+
handshakeTimeout: 5e3,
|
|
372
|
+
maxPayload: 64 * 1024 * 1024,
|
|
373
|
+
perMessageDeflate: false
|
|
374
|
+
});
|
|
375
|
+
let settled = false;
|
|
376
|
+
const fail = (error48) => {
|
|
377
|
+
if (settled) return;
|
|
378
|
+
settled = true;
|
|
379
|
+
socket.terminate();
|
|
380
|
+
reject(error48);
|
|
381
|
+
};
|
|
382
|
+
socket.once("open", () => {
|
|
383
|
+
if (settled) return;
|
|
384
|
+
settled = true;
|
|
385
|
+
resolve2(new _CdpClient(socket));
|
|
386
|
+
});
|
|
387
|
+
socket.once("error", fail);
|
|
388
|
+
socket.once("unexpected-response", (_request, response) => {
|
|
389
|
+
response.resume();
|
|
390
|
+
fail(new Error(`CDP WebSocket upgrade failed with status ${response.statusCode ?? 0}`));
|
|
391
|
+
});
|
|
371
392
|
});
|
|
372
393
|
}
|
|
373
|
-
/** Create a child session client that routes through this connection via sessionId. */
|
|
374
394
|
createChildSession(sessionId) {
|
|
375
395
|
return new CdpChildSession(this, sessionId);
|
|
376
396
|
}
|
|
377
|
-
/** Send a command within a specific CDP session (multiplexed on this connection). */
|
|
378
397
|
sendCommandInSession(sessionId, method, params, timeoutMs = 3e4) {
|
|
379
|
-
return
|
|
380
|
-
if (this._closed) {
|
|
381
|
-
reject(new Error("CDP client is closed"));
|
|
382
|
-
return;
|
|
383
|
-
}
|
|
384
|
-
const id = this.nextId++;
|
|
385
|
-
const timer = setTimeout(() => {
|
|
386
|
-
this.pending.delete(id);
|
|
387
|
-
reject(new Error(`CDP command timeout: ${method}`));
|
|
388
|
-
}, timeoutMs);
|
|
389
|
-
this.pending.set(id, { resolve, reject, timer, sessionId });
|
|
390
|
-
this.sendText(JSON.stringify({ id, method, params: params ?? {}, sessionId }));
|
|
391
|
-
});
|
|
398
|
+
return this.sendRequest(method, params, timeoutMs, sessionId);
|
|
392
399
|
}
|
|
393
|
-
/** Subscribe to events from a specific CDP session. */
|
|
394
400
|
onSession(sessionId, method, callback) {
|
|
395
401
|
if (!this.sessionEventHandlers.has(sessionId)) {
|
|
396
402
|
this.sessionEventHandlers.set(sessionId, /* @__PURE__ */ new Map());
|
|
397
403
|
}
|
|
398
404
|
const sessionMap = this.sessionEventHandlers.get(sessionId);
|
|
399
|
-
if (!sessionMap.has(method))
|
|
400
|
-
sessionMap.set(method, /* @__PURE__ */ new Set());
|
|
401
|
-
}
|
|
405
|
+
if (!sessionMap.has(method)) sessionMap.set(method, /* @__PURE__ */ new Set());
|
|
402
406
|
sessionMap.get(method).add(callback);
|
|
403
407
|
return () => sessionMap.get(method)?.delete(callback);
|
|
404
408
|
}
|
|
405
|
-
|
|
406
|
-
return
|
|
407
|
-
const url2 = new URL(wsUrl);
|
|
408
|
-
const port = parseInt(url2.port || "9222", 10);
|
|
409
|
-
const key = crypto2.randomBytes(16).toString("base64");
|
|
410
|
-
const expectedAccept = crypto2.createHash("sha1").update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").digest("base64");
|
|
411
|
-
const req = http.request({
|
|
412
|
-
host: url2.hostname,
|
|
413
|
-
port,
|
|
414
|
-
path: url2.pathname,
|
|
415
|
-
headers: {
|
|
416
|
-
Connection: "Upgrade",
|
|
417
|
-
Upgrade: "websocket",
|
|
418
|
-
"Sec-WebSocket-Key": key,
|
|
419
|
-
"Sec-WebSocket-Version": "13",
|
|
420
|
-
Host: url2.host
|
|
421
|
-
// No Origin header — Chrome allows connections without Origin,
|
|
422
|
-
// but rejects any Origin not in --remote-allow-origins allowlist.
|
|
423
|
-
}
|
|
424
|
-
});
|
|
425
|
-
let settled = false;
|
|
426
|
-
const fail = (err) => {
|
|
427
|
-
if (settled) return;
|
|
428
|
-
settled = true;
|
|
429
|
-
reject(err);
|
|
430
|
-
};
|
|
431
|
-
req.on("upgrade", (res, socket, head) => {
|
|
432
|
-
if (settled) return;
|
|
433
|
-
if (res.statusCode !== 101) {
|
|
434
|
-
settled = true;
|
|
435
|
-
socket.destroy();
|
|
436
|
-
reject(new Error(`WebSocket upgrade failed with status ${res.statusCode}`));
|
|
437
|
-
return;
|
|
438
|
-
}
|
|
439
|
-
const acceptHeader = res.headers["sec-websocket-accept"];
|
|
440
|
-
if (acceptHeader !== expectedAccept) {
|
|
441
|
-
settled = true;
|
|
442
|
-
socket.destroy();
|
|
443
|
-
reject(new Error("WebSocket handshake key mismatch"));
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
446
|
-
settled = true;
|
|
447
|
-
const client2 = new _CdpClient(socket);
|
|
448
|
-
if (head && head.length > 0) {
|
|
449
|
-
client2.buffer = Buffer.concat([client2.buffer, head]);
|
|
450
|
-
client2.consumeFrames();
|
|
451
|
-
}
|
|
452
|
-
resolve(client2);
|
|
453
|
-
});
|
|
454
|
-
req.on("error", fail);
|
|
455
|
-
req.setTimeout(5e3, () => {
|
|
456
|
-
req.destroy();
|
|
457
|
-
fail(new Error("CDP WebSocket connect timeout"));
|
|
458
|
-
});
|
|
459
|
-
req.end();
|
|
460
|
-
});
|
|
409
|
+
sendCommand(method, params, timeoutMs = 3e4) {
|
|
410
|
+
return this.sendRequest(method, params, timeoutMs);
|
|
461
411
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
const masked = (byte1 & 128) !== 0;
|
|
467
|
-
let payloadLen = byte1 & 127;
|
|
468
|
-
let headerLen = 2;
|
|
469
|
-
if (payloadLen === 126) {
|
|
470
|
-
if (this.buffer.length < 4) return;
|
|
471
|
-
payloadLen = this.buffer.readUInt16BE(2);
|
|
472
|
-
headerLen = 4;
|
|
473
|
-
} else if (payloadLen === 127) {
|
|
474
|
-
if (this.buffer.length < 10) return;
|
|
475
|
-
payloadLen = Number(this.buffer.readBigUInt64BE(2));
|
|
476
|
-
headerLen = 10;
|
|
477
|
-
}
|
|
478
|
-
if (masked) headerLen += 4;
|
|
479
|
-
if (this.buffer.length < headerLen + payloadLen) return;
|
|
480
|
-
const opcode = this.buffer[0] & 15;
|
|
481
|
-
let payload;
|
|
482
|
-
if (masked) {
|
|
483
|
-
const maskKey = this.buffer.subarray(headerLen - 4, headerLen);
|
|
484
|
-
payload = Buffer.from(
|
|
485
|
-
this.buffer.subarray(headerLen, headerLen + payloadLen).map((b, i) => b ^ maskKey[i % 4])
|
|
486
|
-
);
|
|
487
|
-
} else {
|
|
488
|
-
payload = this.buffer.subarray(headerLen, headerLen + payloadLen);
|
|
489
|
-
}
|
|
490
|
-
this.buffer = this.buffer.subarray(headerLen + payloadLen);
|
|
491
|
-
if (opcode === 1 || opcode === 2) {
|
|
492
|
-
try {
|
|
493
|
-
const msg = JSON.parse(payload.toString("utf-8"));
|
|
494
|
-
this.handleMessage(msg);
|
|
495
|
-
} catch {
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
}
|
|
412
|
+
on(method, callback) {
|
|
413
|
+
if (!this.eventHandlers.has(method)) this.eventHandlers.set(method, /* @__PURE__ */ new Set());
|
|
414
|
+
this.eventHandlers.get(method).add(callback);
|
|
415
|
+
return () => this.eventHandlers.get(method)?.delete(callback);
|
|
499
416
|
}
|
|
500
|
-
|
|
501
|
-
if (
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
this.pending.delete(msg.id);
|
|
506
|
-
if (msg.error) {
|
|
507
|
-
pending.reject(new Error(msg.error.message ?? JSON.stringify(msg.error)));
|
|
508
|
-
} else {
|
|
509
|
-
pending.resolve(msg.result ?? {});
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
} else if (msg.method) {
|
|
513
|
-
if (msg.sessionId) {
|
|
514
|
-
const sessionMap = this.sessionEventHandlers.get(msg.sessionId);
|
|
515
|
-
const handlers = sessionMap?.get(msg.method);
|
|
516
|
-
if (handlers) {
|
|
517
|
-
for (const cb of handlers) {
|
|
518
|
-
try {
|
|
519
|
-
cb(msg.params);
|
|
520
|
-
} catch {
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
} else {
|
|
525
|
-
const handlers = this.eventHandlers.get(msg.method);
|
|
526
|
-
if (handlers) {
|
|
527
|
-
for (const cb of handlers) {
|
|
528
|
-
try {
|
|
529
|
-
cb(msg.params);
|
|
530
|
-
} catch {
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
}
|
|
417
|
+
close() {
|
|
418
|
+
if (this._closed) return;
|
|
419
|
+
this._closed = true;
|
|
420
|
+
this.socket.terminate();
|
|
421
|
+
this.rejectPending("CDP connection closed");
|
|
536
422
|
}
|
|
537
|
-
|
|
538
|
-
return
|
|
539
|
-
|
|
423
|
+
get closed() {
|
|
424
|
+
return this._closed;
|
|
425
|
+
}
|
|
426
|
+
sendRequest(method, params, timeoutMs, sessionId) {
|
|
427
|
+
return new Promise((resolve2, reject) => {
|
|
428
|
+
if (this._closed || this.socket.readyState !== WebSocket.OPEN) {
|
|
540
429
|
reject(new Error("CDP client is closed"));
|
|
541
430
|
return;
|
|
542
431
|
}
|
|
@@ -545,51 +434,61 @@ var CdpClient = class _CdpClient {
|
|
|
545
434
|
this.pending.delete(id);
|
|
546
435
|
reject(new Error(`CDP command timeout: ${method}`));
|
|
547
436
|
}, timeoutMs);
|
|
548
|
-
this.pending.set(id, { resolve, reject, timer });
|
|
549
|
-
this.
|
|
437
|
+
this.pending.set(id, { resolve: resolve2, reject, timer, sessionId });
|
|
438
|
+
this.socket.send(
|
|
439
|
+
JSON.stringify({ id, method, params: params ?? {}, ...sessionId ? { sessionId } : {} }),
|
|
440
|
+
(error48) => {
|
|
441
|
+
if (!error48) return;
|
|
442
|
+
const pending = this.pending.get(id);
|
|
443
|
+
if (!pending) return;
|
|
444
|
+
clearTimeout(pending.timer);
|
|
445
|
+
this.pending.delete(id);
|
|
446
|
+
pending.reject(error48);
|
|
447
|
+
}
|
|
448
|
+
);
|
|
550
449
|
});
|
|
551
450
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
451
|
+
consumeMessage(data) {
|
|
452
|
+
try {
|
|
453
|
+
const text = Array.isArray(data) ? Buffer.concat(data).toString("utf8") : Buffer.isBuffer(data) ? data.toString("utf8") : Buffer.from(data).toString("utf8");
|
|
454
|
+
this.handleMessage(JSON.parse(text));
|
|
455
|
+
} catch {
|
|
555
456
|
}
|
|
556
|
-
this.eventHandlers.get(method).add(callback);
|
|
557
|
-
return () => this.eventHandlers.get(method)?.delete(callback);
|
|
558
457
|
}
|
|
559
|
-
|
|
560
|
-
if (
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
header = Buffer.alloc(8);
|
|
572
|
-
header[0] = 129;
|
|
573
|
-
header[1] = 128 | 126;
|
|
574
|
-
header.writeUInt16BE(payload.length, 2);
|
|
575
|
-
maskKey.copy(header, 4);
|
|
576
|
-
} else {
|
|
577
|
-
header = Buffer.alloc(14);
|
|
578
|
-
header[0] = 129;
|
|
579
|
-
header[1] = 128 | 127;
|
|
580
|
-
header.writeBigUInt64BE(BigInt(payload.length), 2);
|
|
581
|
-
maskKey.copy(header, 10);
|
|
458
|
+
handleMessage(msg) {
|
|
459
|
+
if (msg.id !== void 0) {
|
|
460
|
+
const pending = this.pending.get(msg.id);
|
|
461
|
+
if (!pending) return;
|
|
462
|
+
clearTimeout(pending.timer);
|
|
463
|
+
this.pending.delete(msg.id);
|
|
464
|
+
if (msg.error) {
|
|
465
|
+
pending.reject(new Error(msg.error.message ?? JSON.stringify(msg.error)));
|
|
466
|
+
} else {
|
|
467
|
+
pending.resolve(msg.result ?? {});
|
|
468
|
+
}
|
|
469
|
+
return;
|
|
582
470
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
471
|
+
if (!msg.method) return;
|
|
472
|
+
const handlers = msg.sessionId ? this.sessionEventHandlers.get(msg.sessionId)?.get(msg.method) : this.eventHandlers.get(msg.method);
|
|
473
|
+
if (!handlers) return;
|
|
474
|
+
for (const callback of handlers) {
|
|
475
|
+
try {
|
|
476
|
+
callback(msg.params);
|
|
477
|
+
} catch {
|
|
478
|
+
}
|
|
589
479
|
}
|
|
590
480
|
}
|
|
591
|
-
|
|
592
|
-
|
|
481
|
+
handleClosed() {
|
|
482
|
+
if (this._closed) return;
|
|
483
|
+
this._closed = true;
|
|
484
|
+
this.rejectPending("CDP connection closed");
|
|
485
|
+
}
|
|
486
|
+
rejectPending(message) {
|
|
487
|
+
for (const [id, pending] of this.pending) {
|
|
488
|
+
clearTimeout(pending.timer);
|
|
489
|
+
pending.reject(new Error(message));
|
|
490
|
+
this.pending.delete(id);
|
|
491
|
+
}
|
|
593
492
|
}
|
|
594
493
|
};
|
|
595
494
|
|
|
@@ -3056,7 +2955,7 @@ function installPageObserverInPage(maxBatches = 50) {
|
|
|
3056
2955
|
});
|
|
3057
2956
|
state.waitSince = (checkpoint, checkpointFocus, quietMs, firstChangeTimeoutMs, timeoutMs) => {
|
|
3058
2957
|
const startedAt = performance.now();
|
|
3059
|
-
return new Promise((
|
|
2958
|
+
return new Promise((resolve2) => {
|
|
3060
2959
|
let completed = false;
|
|
3061
2960
|
let quietTimer;
|
|
3062
2961
|
let firstChangeTimer;
|
|
@@ -3121,7 +3020,7 @@ function installPageObserverInPage(maxBatches = 50) {
|
|
|
3121
3020
|
if (structuralMutationCount > 0 && unclassifiedStructuralMutationCount > 0) {
|
|
3122
3021
|
snapshotReasons.push("unclassified-structure");
|
|
3123
3022
|
}
|
|
3124
|
-
|
|
3023
|
+
resolve2({
|
|
3125
3024
|
mode: "delta",
|
|
3126
3025
|
scope: "main-document",
|
|
3127
3026
|
checkpoint,
|
|
@@ -3360,14 +3259,14 @@ function createNavigationSettlementTracker(options) {
|
|
|
3360
3259
|
return Promise.resolve(true);
|
|
3361
3260
|
if (timeoutMs <= 0 || disposed)
|
|
3362
3261
|
return Promise.resolve(false);
|
|
3363
|
-
return new Promise((
|
|
3262
|
+
return new Promise((resolve2) => {
|
|
3364
3263
|
const initialDeadline = performance.now() + timeoutMs;
|
|
3365
3264
|
const hardDeadline = initialDeadline + 4e3;
|
|
3366
3265
|
let timer;
|
|
3367
3266
|
const waiter = (didStart) => {
|
|
3368
3267
|
clearTimeout(timer);
|
|
3369
3268
|
startWaiters.delete(waiter);
|
|
3370
|
-
|
|
3269
|
+
resolve2(didStart);
|
|
3371
3270
|
};
|
|
3372
3271
|
const check2 = () => {
|
|
3373
3272
|
if (started) {
|
|
@@ -3389,26 +3288,26 @@ function createNavigationSettlementTracker(options) {
|
|
|
3389
3288
|
const waitForResult = (timeoutMs) => {
|
|
3390
3289
|
if (completed)
|
|
3391
3290
|
return Promise.resolve(completed);
|
|
3392
|
-
return new Promise((
|
|
3291
|
+
return new Promise((resolve2) => {
|
|
3393
3292
|
const waiter = (result) => {
|
|
3394
3293
|
clearTimeout(timer);
|
|
3395
3294
|
resultWaiters.delete(waiter);
|
|
3396
|
-
|
|
3295
|
+
resolve2(result);
|
|
3397
3296
|
};
|
|
3398
3297
|
const timer = setTimeout(() => {
|
|
3399
3298
|
resultWaiters.delete(waiter);
|
|
3400
3299
|
finish(documentComplete, false, "timeout");
|
|
3401
3300
|
if (completed)
|
|
3402
|
-
|
|
3301
|
+
resolve2(completed);
|
|
3403
3302
|
}, timeoutMs);
|
|
3404
3303
|
resultWaiters.add(waiter);
|
|
3405
3304
|
});
|
|
3406
3305
|
};
|
|
3407
3306
|
const waitForNetworkIdle = (timeoutMs) => {
|
|
3408
3307
|
const waitStartedAt = performance.now();
|
|
3409
|
-
return new Promise((
|
|
3308
|
+
return new Promise((resolve2) => {
|
|
3410
3309
|
const finishWait = (ready, settledBy) => {
|
|
3411
|
-
|
|
3310
|
+
resolve2({
|
|
3412
3311
|
ready,
|
|
3413
3312
|
settledBy,
|
|
3414
3313
|
pendingRequests: pendingRequests2.size,
|
|
@@ -4848,7 +4747,7 @@ async function setupBufferListeners(client2, buffers) {
|
|
|
4848
4747
|
|
|
4849
4748
|
// src/cdp-backend/discover.ts
|
|
4850
4749
|
import fs from "node:fs";
|
|
4851
|
-
import
|
|
4750
|
+
import http from "node:http";
|
|
4852
4751
|
import os from "node:os";
|
|
4853
4752
|
import path from "node:path";
|
|
4854
4753
|
function chromeUserDataDir() {
|
|
@@ -4876,13 +4775,13 @@ function readDevToolsActivePort(userDataDir = chromeUserDataDir()) {
|
|
|
4876
4775
|
}
|
|
4877
4776
|
}
|
|
4878
4777
|
async function discoverTargets(port = 9222) {
|
|
4879
|
-
return new Promise((
|
|
4880
|
-
const req =
|
|
4778
|
+
return new Promise((resolve2, reject) => {
|
|
4779
|
+
const req = http.get(`http://localhost:${port}/json`, (res) => {
|
|
4881
4780
|
let data = "";
|
|
4882
4781
|
res.on("data", (chunk) => data += chunk);
|
|
4883
4782
|
res.on("end", () => {
|
|
4884
4783
|
try {
|
|
4885
|
-
|
|
4784
|
+
resolve2(JSON.parse(data));
|
|
4886
4785
|
} catch (e) {
|
|
4887
4786
|
reject(new Error(`Failed to parse CDP targets: ${e}`));
|
|
4888
4787
|
}
|
|
@@ -4909,6 +4808,8 @@ async function isCdpAvailable(port = 9222, userDataDir) {
|
|
|
4909
4808
|
var CdpSession = class {
|
|
4910
4809
|
port;
|
|
4911
4810
|
userDataDir;
|
|
4811
|
+
endpointUrl;
|
|
4812
|
+
endpointResolver;
|
|
4912
4813
|
browserClient = null;
|
|
4913
4814
|
pageSessions = /* @__PURE__ */ new Map();
|
|
4914
4815
|
// targetId → PageSession
|
|
@@ -4922,6 +4823,8 @@ var CdpSession = class {
|
|
|
4922
4823
|
}
|
|
4923
4824
|
this.port = options.port ?? 9222;
|
|
4924
4825
|
this.userDataDir = options.userDataDir;
|
|
4826
|
+
this.endpointUrl = options.endpointUrl;
|
|
4827
|
+
this.endpointResolver = options.endpointResolver;
|
|
4925
4828
|
}
|
|
4926
4829
|
// ── Browser-level ──────────────────────────────────────────────────────────
|
|
4927
4830
|
async getBrowserClient() {
|
|
@@ -4999,7 +4902,13 @@ var CdpSession = class {
|
|
|
4999
4902
|
5e3
|
|
5000
4903
|
);
|
|
5001
4904
|
client2 = browser.createChildSession(sessionId);
|
|
5002
|
-
} catch {
|
|
4905
|
+
} catch (error48) {
|
|
4906
|
+
if (this.isRemote()) {
|
|
4907
|
+
throw new Error(
|
|
4908
|
+
`Failed to attach to remote CDP target ${target.id}: ${error48 instanceof Error ? error48.message : String(error48)}`,
|
|
4909
|
+
{ cause: error48 }
|
|
4910
|
+
);
|
|
4911
|
+
}
|
|
5003
4912
|
client2 = await CdpClient.connect(target.webSocketDebuggerUrl);
|
|
5004
4913
|
}
|
|
5005
4914
|
let tabId;
|
|
@@ -5029,6 +4938,7 @@ var CdpSession = class {
|
|
|
5029
4938
|
return session;
|
|
5030
4939
|
}
|
|
5031
4940
|
async findTargetById(targetId) {
|
|
4941
|
+
if (this.isRemote()) return this.findTargetByIdViaCdp(targetId);
|
|
5032
4942
|
try {
|
|
5033
4943
|
const targets = await discoverTargets(this.effectivePort());
|
|
5034
4944
|
return targets.find((t) => t.id === targetId && t.webSocketDebuggerUrl) ?? null;
|
|
@@ -5037,6 +4947,7 @@ var CdpSession = class {
|
|
|
5037
4947
|
}
|
|
5038
4948
|
}
|
|
5039
4949
|
async findDefaultPageTarget() {
|
|
4950
|
+
if (this.isRemote()) return this.findDefaultPageTargetViaCdp();
|
|
5040
4951
|
try {
|
|
5041
4952
|
const targets = await discoverTargets(this.effectivePort());
|
|
5042
4953
|
return targets.find(
|
|
@@ -5056,6 +4967,14 @@ var CdpSession = class {
|
|
|
5056
4967
|
* Priority: DevToolsActivePort file → HTTP /json/version
|
|
5057
4968
|
*/
|
|
5058
4969
|
async resolveBrowserWsUrl() {
|
|
4970
|
+
const configuredEndpoint = this.endpointResolver ? await this.endpointResolver() : this.endpointUrl;
|
|
4971
|
+
if (configuredEndpoint) {
|
|
4972
|
+
const url2 = new URL(configuredEndpoint);
|
|
4973
|
+
if (url2.protocol !== "ws:" && url2.protocol !== "wss:") {
|
|
4974
|
+
throw new Error(`Unsupported CDP endpoint protocol: ${url2.protocol}`);
|
|
4975
|
+
}
|
|
4976
|
+
return url2.toString();
|
|
4977
|
+
}
|
|
5059
4978
|
const fileInfo = readDevToolsActivePort(this.userDataDir);
|
|
5060
4979
|
if (fileInfo) {
|
|
5061
4980
|
return `ws://localhost:${fileInfo.port}${fileInfo.browserWsPath}`;
|
|
@@ -5075,6 +4994,9 @@ var CdpSession = class {
|
|
|
5075
4994
|
const port = this.effectivePort();
|
|
5076
4995
|
return `ws://localhost:${port}/devtools/page/${targetId}`;
|
|
5077
4996
|
}
|
|
4997
|
+
isRemote() {
|
|
4998
|
+
return Boolean(this.endpointUrl || this.endpointResolver);
|
|
4999
|
+
}
|
|
5078
5000
|
async findTargetByIdViaCdp(targetId) {
|
|
5079
5001
|
try {
|
|
5080
5002
|
const browser = await this.getBrowserClient();
|
|
@@ -5114,13 +5036,13 @@ var CdpSession = class {
|
|
|
5114
5036
|
}
|
|
5115
5037
|
}
|
|
5116
5038
|
fetchVersionInfo() {
|
|
5117
|
-
return new Promise((
|
|
5118
|
-
const req =
|
|
5039
|
+
return new Promise((resolve2, reject) => {
|
|
5040
|
+
const req = http2.get(`http://localhost:${this.port}/json/version`, (res) => {
|
|
5119
5041
|
let data = "";
|
|
5120
5042
|
res.on("data", (chunk) => data += chunk);
|
|
5121
5043
|
res.on("end", () => {
|
|
5122
5044
|
try {
|
|
5123
|
-
|
|
5045
|
+
resolve2(JSON.parse(data));
|
|
5124
5046
|
} catch (e) {
|
|
5125
5047
|
reject(new Error(`Failed to parse CDP version info: ${e}`));
|
|
5126
5048
|
}
|
|
@@ -5829,15 +5751,15 @@ async function releaseCdpControl(session) {
|
|
|
5829
5751
|
|
|
5830
5752
|
// src/cdp-backend/cdp-utils.ts
|
|
5831
5753
|
import https from "node:https";
|
|
5832
|
-
import
|
|
5754
|
+
import http3 from "node:http";
|
|
5833
5755
|
var TYPE_INTO_ELEMENT_SRC = typeIntoElement.toString();
|
|
5834
5756
|
var CLICK_ELEMENT_VIA_JS_SRC = clickElementViaJS.toString();
|
|
5835
5757
|
var GET_CLICK_COORDS_FROM_NODE_SRC = getClickCoordsFromNode.toString();
|
|
5836
5758
|
function nodeFetch(urlStr, options = {}) {
|
|
5837
|
-
return new Promise((
|
|
5759
|
+
return new Promise((resolve2, reject) => {
|
|
5838
5760
|
const url2 = new URL(urlStr);
|
|
5839
5761
|
const isHttps = url2.protocol === "https:";
|
|
5840
|
-
const lib = isHttps ? https :
|
|
5762
|
+
const lib = isHttps ? https : http3;
|
|
5841
5763
|
const { method = "GET", headers = {}, body, timeoutMs = 3e4 } = options;
|
|
5842
5764
|
const req = lib.request(
|
|
5843
5765
|
{
|
|
@@ -5857,7 +5779,7 @@ function nodeFetch(urlStr, options = {}) {
|
|
|
5857
5779
|
res.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
5858
5780
|
res.on("end", () => {
|
|
5859
5781
|
const bodyBuffer = Buffer.concat(chunks);
|
|
5860
|
-
|
|
5782
|
+
resolve2({
|
|
5861
5783
|
status: res.statusCode ?? 0,
|
|
5862
5784
|
statusText: res.statusMessage ?? "",
|
|
5863
5785
|
headers: responseHeaders,
|
|
@@ -5914,7 +5836,7 @@ ${value}\r
|
|
|
5914
5836
|
return { contentType: `multipart/form-data; boundary=${boundary}`, body };
|
|
5915
5837
|
}
|
|
5916
5838
|
async function waitForPageLoad(session, timeoutMs) {
|
|
5917
|
-
return new Promise((
|
|
5839
|
+
return new Promise((resolve2, reject) => {
|
|
5918
5840
|
let settled = false;
|
|
5919
5841
|
let removeLoadListener = () => {
|
|
5920
5842
|
};
|
|
@@ -5924,7 +5846,7 @@ async function waitForPageLoad(session, timeoutMs) {
|
|
|
5924
5846
|
clearTimeout(timer);
|
|
5925
5847
|
removeLoadListener();
|
|
5926
5848
|
if (error48) reject(error48);
|
|
5927
|
-
else
|
|
5849
|
+
else resolve2();
|
|
5928
5850
|
};
|
|
5929
5851
|
const timer = setTimeout(() => {
|
|
5930
5852
|
finish(new Error(`Page load timeout after ${timeoutMs}ms`));
|
|
@@ -7017,12 +6939,12 @@ function resolveCloudConnectorCommand() {
|
|
|
7017
6939
|
};
|
|
7018
6940
|
}
|
|
7019
6941
|
function startCloudConnector(serverUrl) {
|
|
7020
|
-
return new Promise((
|
|
6942
|
+
return new Promise((resolve2) => {
|
|
7021
6943
|
const existingPid = findLiveConnector(serverUrl);
|
|
7022
6944
|
if (existingPid) {
|
|
7023
6945
|
logFn(`Reusing existing cloud connector for ${serverUrl} (pid=${existingPid})`);
|
|
7024
6946
|
const entry = registerConnector(serverUrl, existingPid);
|
|
7025
|
-
|
|
6947
|
+
resolve2({
|
|
7026
6948
|
success: true,
|
|
7027
6949
|
pid: existingPid,
|
|
7028
6950
|
...entry.connectorId ? { connectorId: entry.connectorId } : {},
|
|
@@ -7055,14 +6977,14 @@ function startCloudConnector(serverUrl) {
|
|
|
7055
6977
|
clearTimeout(startupTimer);
|
|
7056
6978
|
if (ok && child.pid) {
|
|
7057
6979
|
const entry = registerConnector(serverUrl, child.pid, child);
|
|
7058
|
-
|
|
6980
|
+
resolve2({
|
|
7059
6981
|
success: true,
|
|
7060
6982
|
pid: child.pid,
|
|
7061
6983
|
...entry.connectorId ? { connectorId: entry.connectorId } : {},
|
|
7062
6984
|
...entry.name ? { name: entry.name } : {}
|
|
7063
6985
|
});
|
|
7064
6986
|
} else {
|
|
7065
|
-
|
|
6987
|
+
resolve2({ success: false, error: result.error || "Failed to spawn cloud connector" });
|
|
7066
6988
|
}
|
|
7067
6989
|
};
|
|
7068
6990
|
child.once("error", (error48) => {
|
|
@@ -7674,7 +7596,7 @@ async function cdpWaitForTracknick(session, options = {}) {
|
|
|
7674
7596
|
latest = await cdpGetTracknick(session);
|
|
7675
7597
|
if (expected && latest === expected) return latest;
|
|
7676
7598
|
if (!expected && latest && latest !== previous) return latest;
|
|
7677
|
-
await new Promise((
|
|
7599
|
+
await new Promise((resolve2) => setTimeout(resolve2, 500));
|
|
7678
7600
|
}
|
|
7679
7601
|
return latest || await cdpGetTracknick(session);
|
|
7680
7602
|
}
|
|
@@ -7684,7 +7606,7 @@ async function cdpOpenAndCloseTarget(cdpSession2, url2) {
|
|
|
7684
7606
|
url: url2,
|
|
7685
7607
|
background: true
|
|
7686
7608
|
});
|
|
7687
|
-
await new Promise((
|
|
7609
|
+
await new Promise((resolve2) => setTimeout(resolve2, 3500));
|
|
7688
7610
|
await browser.sendCommand("Target.closeTarget", { targetId }).catch(() => {
|
|
7689
7611
|
});
|
|
7690
7612
|
}
|
|
@@ -8434,7 +8356,7 @@ async function cdpPageWait(session, data) {
|
|
|
8434
8356
|
const options = resolvePageWaitInput(data);
|
|
8435
8357
|
const startedAt = Date.now();
|
|
8436
8358
|
if (options.mode === "time") {
|
|
8437
|
-
await new Promise((
|
|
8359
|
+
await new Promise((resolve2) => setTimeout(resolve2, options.time));
|
|
8438
8360
|
return { success: true, waited: true, elapsed: options.time, mode: options.mode };
|
|
8439
8361
|
}
|
|
8440
8362
|
const expression = options.mode === "selector" ? `!!document.querySelector(${JSON.stringify(options.selector)})` : options.condition;
|
|
@@ -8459,7 +8381,7 @@ async function cdpPageWait(session, data) {
|
|
|
8459
8381
|
value
|
|
8460
8382
|
};
|
|
8461
8383
|
}
|
|
8462
|
-
await new Promise((
|
|
8384
|
+
await new Promise((resolve2) => setTimeout(resolve2, options.interval));
|
|
8463
8385
|
}
|
|
8464
8386
|
if (options.mode === "selector") {
|
|
8465
8387
|
throw new Error(
|
|
@@ -8530,7 +8452,7 @@ async function waitForHistoryIndex(session, targetIndex, timeoutMs) {
|
|
|
8530
8452
|
}
|
|
8531
8453
|
} catch {
|
|
8532
8454
|
}
|
|
8533
|
-
await new Promise((
|
|
8455
|
+
await new Promise((resolve2) => setTimeout(resolve2, 50));
|
|
8534
8456
|
}
|
|
8535
8457
|
throw new Error(`Page history navigation timeout after ${timeoutMs}ms`);
|
|
8536
8458
|
}
|
|
@@ -8678,7 +8600,7 @@ async function readCurrentUrl(session, action) {
|
|
|
8678
8600
|
return url2;
|
|
8679
8601
|
}
|
|
8680
8602
|
function reloadPageAndWait(session, timeoutMs) {
|
|
8681
|
-
return new Promise((
|
|
8603
|
+
return new Promise((resolve2, reject) => {
|
|
8682
8604
|
let settled = false;
|
|
8683
8605
|
let removeListener = () => {
|
|
8684
8606
|
};
|
|
@@ -8688,7 +8610,7 @@ function reloadPageAndWait(session, timeoutMs) {
|
|
|
8688
8610
|
clearTimeout(timer);
|
|
8689
8611
|
removeListener();
|
|
8690
8612
|
if (error48) reject(error48);
|
|
8691
|
-
else
|
|
8613
|
+
else resolve2();
|
|
8692
8614
|
};
|
|
8693
8615
|
const timer = setTimeout(() => {
|
|
8694
8616
|
finish(new Error(`Page load timeout after ${timeoutMs}ms`));
|
|
@@ -9137,6 +9059,10 @@ async function cdpExportCookies(session, domains) {
|
|
|
9137
9059
|
async function cdpImportCookies(session, cookies) {
|
|
9138
9060
|
if (cookies.length === 0) return 0;
|
|
9139
9061
|
const browser = await session.getBrowserClient();
|
|
9062
|
+
return cdpImportCookiesWithClient(browser, cookies);
|
|
9063
|
+
}
|
|
9064
|
+
async function cdpImportCookiesWithClient(browser, cookies) {
|
|
9065
|
+
if (cookies.length === 0) return 0;
|
|
9140
9066
|
await browser.sendCommand("Storage.setCookies", { cookies });
|
|
9141
9067
|
return cookies.length;
|
|
9142
9068
|
}
|
|
@@ -9263,6 +9189,7 @@ function browserSummary(record2, running) {
|
|
|
9263
9189
|
return {
|
|
9264
9190
|
browserId: record2.browserId,
|
|
9265
9191
|
name: record2.name,
|
|
9192
|
+
provider: "local",
|
|
9266
9193
|
headless: record2.headless,
|
|
9267
9194
|
persistent: record2.persistent,
|
|
9268
9195
|
cdpPort: record2.cdpPort,
|
|
@@ -9329,12 +9256,15 @@ function findManagedRecord(selector) {
|
|
|
9329
9256
|
({ record: record2 }) => record2.browserId.toLowerCase() === normalized || record2.name.toLowerCase() === normalized
|
|
9330
9257
|
)?.record ?? null;
|
|
9331
9258
|
}
|
|
9259
|
+
function hasManagedBrowser(selector) {
|
|
9260
|
+
return findManagedRecord(selector) !== null;
|
|
9261
|
+
}
|
|
9332
9262
|
async function waitForActivePort(userDataDir) {
|
|
9333
9263
|
const deadline = Date.now() + LAUNCH_TIMEOUT_MS;
|
|
9334
9264
|
while (Date.now() < deadline) {
|
|
9335
9265
|
const info = readDevToolsActivePort(userDataDir);
|
|
9336
9266
|
if (info) return info.port;
|
|
9337
|
-
await new Promise((
|
|
9267
|
+
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
9338
9268
|
}
|
|
9339
9269
|
throw new Error(`Chrome did not expose a CDP port within ${LAUNCH_TIMEOUT_MS}ms`);
|
|
9340
9270
|
}
|
|
@@ -9344,7 +9274,7 @@ async function waitForBrowserRegistration(browserId, expectedPid) {
|
|
|
9344
9274
|
while (Date.now() < deadline) {
|
|
9345
9275
|
const record2 = readRecord(file2);
|
|
9346
9276
|
if (record2?.pid === expectedPid && isAlive(expectedPid)) return;
|
|
9347
|
-
await new Promise((
|
|
9277
|
+
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
9348
9278
|
}
|
|
9349
9279
|
throw new Error(`Managed browser ${browserId} did not register within ${LAUNCH_TIMEOUT_MS}ms`);
|
|
9350
9280
|
}
|
|
@@ -9366,7 +9296,7 @@ async function stopProcess(pid, commandMarker) {
|
|
|
9366
9296
|
signalProcess(pid, "SIGTERM", commandMarker);
|
|
9367
9297
|
const deadline = Date.now() + 3e3;
|
|
9368
9298
|
while (Date.now() < deadline && isManagedProcess(pid, commandMarker)) {
|
|
9369
|
-
await new Promise((
|
|
9299
|
+
await new Promise((resolve2) => setTimeout(resolve2, 50));
|
|
9370
9300
|
}
|
|
9371
9301
|
if (isManagedProcess(pid, commandMarker)) signalProcess(pid, "SIGKILL", commandMarker);
|
|
9372
9302
|
}
|
|
@@ -9435,6 +9365,9 @@ function acquireLaunchLock(browserId) {
|
|
|
9435
9365
|
};
|
|
9436
9366
|
}
|
|
9437
9367
|
async function launchManagedBrowser(input, deps) {
|
|
9368
|
+
if (input.imageId !== void 0) {
|
|
9369
|
+
throw new Error("imageId is only supported by the AgentBay browser provider");
|
|
9370
|
+
}
|
|
9438
9371
|
const name = validateName(input.name);
|
|
9439
9372
|
const browserId = managedBrowserId(name);
|
|
9440
9373
|
validateTdbankSelector(input);
|
|
@@ -9470,9 +9403,9 @@ async function launchManagedBrowser(input, deps) {
|
|
|
9470
9403
|
stdio: ["ignore", "ignore", logFd],
|
|
9471
9404
|
windowsHide: headless
|
|
9472
9405
|
});
|
|
9473
|
-
await new Promise((
|
|
9406
|
+
await new Promise((resolve2, reject) => {
|
|
9474
9407
|
chrome.once("error", reject);
|
|
9475
|
-
chrome.once("spawn",
|
|
9408
|
+
chrome.once("spawn", resolve2);
|
|
9476
9409
|
});
|
|
9477
9410
|
chromePid = chrome.pid ?? 0;
|
|
9478
9411
|
if (!chromePid) throw new Error("Chrome launched without a process id");
|
|
@@ -9511,9 +9444,9 @@ async function launchManagedBrowser(input, deps) {
|
|
|
9511
9444
|
],
|
|
9512
9445
|
{ detached: true, stdio: "ignore", windowsHide: true }
|
|
9513
9446
|
);
|
|
9514
|
-
await new Promise((
|
|
9447
|
+
await new Promise((resolve2, reject) => {
|
|
9515
9448
|
host.once("error", reject);
|
|
9516
|
-
host.once("spawn",
|
|
9449
|
+
host.once("spawn", resolve2);
|
|
9517
9450
|
});
|
|
9518
9451
|
hostPid = host.pid ?? 0;
|
|
9519
9452
|
if (!hostPid) throw new Error("Native host launched without a process id");
|
|
@@ -9566,6 +9499,360 @@ async function closeManagedBrowser(selector, options = {}) {
|
|
|
9566
9499
|
return { browserId: record2.browserId, closed: true, profileDeleted: deleteProfile };
|
|
9567
9500
|
}
|
|
9568
9501
|
|
|
9502
|
+
// src/agentbay-browser.ts
|
|
9503
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
9504
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
9505
|
+
import { homedir as homedir2 } from "node:os";
|
|
9506
|
+
import { dirname as dirname3, join as join4, parse, resolve } from "node:path";
|
|
9507
|
+
import { fileURLToPath } from "node:url";
|
|
9508
|
+
var AGENTBAY_BROWSERS_SUBDIR = "agentbay-browsers";
|
|
9509
|
+
var DEFAULT_AGENTBAY_IMAGE_ID = "imgc-0aae4rgl8kvagdv1j";
|
|
9510
|
+
var sdkPromise = null;
|
|
9511
|
+
async function loadSdk() {
|
|
9512
|
+
sdkPromise ??= import("wuying-agentbay-sdk").then((sdk) => {
|
|
9513
|
+
sdk.setupLogger({ level: "ERROR", enableConsole: false });
|
|
9514
|
+
return sdk;
|
|
9515
|
+
});
|
|
9516
|
+
return sdkPromise;
|
|
9517
|
+
}
|
|
9518
|
+
async function createClient(apiKey) {
|
|
9519
|
+
const { AgentBay } = await loadSdk();
|
|
9520
|
+
return new AgentBay({ apiKey });
|
|
9521
|
+
}
|
|
9522
|
+
function agentBayBrowserId(name) {
|
|
9523
|
+
return `managed:agentbay:${name.toLocaleLowerCase("en-US")}`;
|
|
9524
|
+
}
|
|
9525
|
+
function envValue(text, key) {
|
|
9526
|
+
for (const line of text.split(/\r?\n/)) {
|
|
9527
|
+
const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)\s*$/.exec(line);
|
|
9528
|
+
if (!match || match[1] !== key) continue;
|
|
9529
|
+
let value = (match[2] ?? "").trim();
|
|
9530
|
+
if (value.length >= 2 && (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'"))) {
|
|
9531
|
+
value = value.slice(1, -1);
|
|
9532
|
+
} else {
|
|
9533
|
+
value = value.replace(/\s+#.*$/, "").trim();
|
|
9534
|
+
}
|
|
9535
|
+
return value || void 0;
|
|
9536
|
+
}
|
|
9537
|
+
return void 0;
|
|
9538
|
+
}
|
|
9539
|
+
function envFilesUpward(start) {
|
|
9540
|
+
const files = [];
|
|
9541
|
+
let current = resolve(start);
|
|
9542
|
+
while (true) {
|
|
9543
|
+
files.push(join4(current, ".env"));
|
|
9544
|
+
const parent = dirname3(current);
|
|
9545
|
+
if (parent === current || current === parse(current).root) break;
|
|
9546
|
+
current = parent;
|
|
9547
|
+
}
|
|
9548
|
+
return files;
|
|
9549
|
+
}
|
|
9550
|
+
function resolveAgentBayApiKey() {
|
|
9551
|
+
const inherited = process.env.AGENTBAY_KEY?.trim() || process.env.AGENTBAY_API_KEY?.trim();
|
|
9552
|
+
if (inherited) return inherited;
|
|
9553
|
+
const moduleDir = dirname3(fileURLToPath(import.meta.url));
|
|
9554
|
+
const candidates = [
|
|
9555
|
+
...process.env.MEARL_ENV_FILE ? [resolve(process.env.MEARL_ENV_FILE)] : [],
|
|
9556
|
+
...envFilesUpward(process.cwd()),
|
|
9557
|
+
...envFilesUpward(moduleDir),
|
|
9558
|
+
join4(homedir2(), ".mearl", ".env")
|
|
9559
|
+
];
|
|
9560
|
+
for (const file2 of new Set(candidates)) {
|
|
9561
|
+
if (!existsSync4(file2)) continue;
|
|
9562
|
+
try {
|
|
9563
|
+
const text = readFileSync4(file2, "utf8");
|
|
9564
|
+
const value = envValue(text, "AGENTBAY_KEY") ?? envValue(text, "AGENTBAY_API_KEY");
|
|
9565
|
+
if (value) return value;
|
|
9566
|
+
} catch {
|
|
9567
|
+
}
|
|
9568
|
+
}
|
|
9569
|
+
throw new Error(
|
|
9570
|
+
"AgentBay API key not found. Set AGENTBAY_KEY in the environment, project .env, or ~/.mearl/.env."
|
|
9571
|
+
);
|
|
9572
|
+
}
|
|
9573
|
+
function validateAgentBayInput(input) {
|
|
9574
|
+
if (input.headless === true) {
|
|
9575
|
+
throw new Error("headless=true is not supported by the AgentBay browser provider");
|
|
9576
|
+
}
|
|
9577
|
+
if (input.persistent === true) {
|
|
9578
|
+
throw new Error("persistent is not supported by the AgentBay CDP provider yet");
|
|
9579
|
+
}
|
|
9580
|
+
if (input.executablePath) {
|
|
9581
|
+
throw new Error("executablePath is only supported by the local browser provider");
|
|
9582
|
+
}
|
|
9583
|
+
if (input.accountId !== void 0 || input.havanaId !== void 0 || input.site !== void 0 || typeof input.query === "string" && input.query.trim()) {
|
|
9584
|
+
throw new Error("TDBank login parameters are only supported by the local browser provider");
|
|
9585
|
+
}
|
|
9586
|
+
}
|
|
9587
|
+
function resolveAgentBayImageId(value) {
|
|
9588
|
+
if (value === void 0) return DEFAULT_AGENTBAY_IMAGE_ID;
|
|
9589
|
+
const imageId = typeof value === "string" ? value.trim() : "";
|
|
9590
|
+
if (!imageId || imageId.length > 128 || !/^[A-Za-z0-9][A-Za-z0-9._:-]*$/.test(imageId)) {
|
|
9591
|
+
throw new Error("imageId must be a valid AgentBay image alias or image ID");
|
|
9592
|
+
}
|
|
9593
|
+
return imageId;
|
|
9594
|
+
}
|
|
9595
|
+
function normalizeDesktopUserAgent(value) {
|
|
9596
|
+
const userAgent = typeof value === "string" ? value.trim() : "";
|
|
9597
|
+
if (!userAgent) throw new Error("Could not determine the control browser user agent");
|
|
9598
|
+
return userAgent.replace(/\bHeadlessChrome\//g, "Chrome/");
|
|
9599
|
+
}
|
|
9600
|
+
function normalizeAgentBayAccessUrl(value) {
|
|
9601
|
+
const candidate = typeof value === "string" ? value.trim() : "";
|
|
9602
|
+
if (!candidate) return void 0;
|
|
9603
|
+
try {
|
|
9604
|
+
const url2 = new URL(candidate);
|
|
9605
|
+
return url2.protocol === "https:" || url2.protocol === "http:" ? url2.toString() : void 0;
|
|
9606
|
+
} catch {
|
|
9607
|
+
return void 0;
|
|
9608
|
+
}
|
|
9609
|
+
}
|
|
9610
|
+
function browserSummary2(record2, running) {
|
|
9611
|
+
const accessUrl = normalizeAgentBayAccessUrl(record2.accessUrl);
|
|
9612
|
+
return {
|
|
9613
|
+
browserId: record2.browserId,
|
|
9614
|
+
name: record2.name,
|
|
9615
|
+
provider: "agentbay",
|
|
9616
|
+
headless: false,
|
|
9617
|
+
persistent: false,
|
|
9618
|
+
agentbaySessionId: record2.sessionId,
|
|
9619
|
+
...record2.imageId ? { agentbayImageId: record2.imageId } : {},
|
|
9620
|
+
...accessUrl ? { agentbayAccessUrl: accessUrl } : {},
|
|
9621
|
+
createdAt: record2.createdAt,
|
|
9622
|
+
...record2.copiedCookies ? { copiedCookies: record2.copiedCookies } : {},
|
|
9623
|
+
running
|
|
9624
|
+
};
|
|
9625
|
+
}
|
|
9626
|
+
function listRecords2() {
|
|
9627
|
+
const records = [];
|
|
9628
|
+
for (const file2 of listRecordFiles(keyedDir(AGENTBAY_BROWSERS_SUBDIR))) {
|
|
9629
|
+
const record2 = readRecord(file2);
|
|
9630
|
+
if (!record2) {
|
|
9631
|
+
removeRecord(file2);
|
|
9632
|
+
continue;
|
|
9633
|
+
}
|
|
9634
|
+
const running = isManagedProcess(record2.pid, `--browser-id ${record2.browserId}`);
|
|
9635
|
+
if (!running) removeRecord(keyedConfigFile("browsers", record2.browserId));
|
|
9636
|
+
records.push({ record: record2, running });
|
|
9637
|
+
}
|
|
9638
|
+
return records;
|
|
9639
|
+
}
|
|
9640
|
+
function findRecord(selector) {
|
|
9641
|
+
const normalized = selector.trim().toLowerCase();
|
|
9642
|
+
return listRecords2().find(
|
|
9643
|
+
({ record: record2 }) => record2.browserId.toLowerCase() === normalized || record2.name.toLowerCase() === normalized
|
|
9644
|
+
)?.record ?? null;
|
|
9645
|
+
}
|
|
9646
|
+
function hasAgentBayBrowser(selector) {
|
|
9647
|
+
return findRecord(selector) !== null;
|
|
9648
|
+
}
|
|
9649
|
+
function listAgentBayBrowsers() {
|
|
9650
|
+
return listRecords2().map(({ record: record2, running }) => browserSummary2(record2, running));
|
|
9651
|
+
}
|
|
9652
|
+
async function requireSession(sessionId, apiKey) {
|
|
9653
|
+
const agentBay = await createClient(apiKey);
|
|
9654
|
+
const result = await agentBay.get(sessionId);
|
|
9655
|
+
if (!result.success || !result.session) {
|
|
9656
|
+
throw new Error(result.errorMessage || `AgentBay session not found: ${sessionId}`);
|
|
9657
|
+
}
|
|
9658
|
+
return result.session;
|
|
9659
|
+
}
|
|
9660
|
+
async function resolveAgentBayEndpoint(sessionId) {
|
|
9661
|
+
const apiKey = resolveAgentBayApiKey();
|
|
9662
|
+
const { AgentBay, GetCdpLinkRequest } = await loadSdk();
|
|
9663
|
+
const agentBay = new AgentBay({ apiKey });
|
|
9664
|
+
const response = await agentBay.client.getCdpLink(
|
|
9665
|
+
new GetCdpLinkRequest({ authorization: `Bearer ${apiKey}`, sessionId })
|
|
9666
|
+
);
|
|
9667
|
+
const endpoint = response.body?.success ? response.body.data?.url : void 0;
|
|
9668
|
+
if (!endpoint) {
|
|
9669
|
+
throw new Error(response.body?.message || `Failed to get AgentBay CDP link: ${sessionId}`);
|
|
9670
|
+
}
|
|
9671
|
+
const url2 = new URL(endpoint);
|
|
9672
|
+
if (url2.protocol !== "ws:" && url2.protocol !== "wss:") {
|
|
9673
|
+
throw new Error(`AgentBay returned an unsupported CDP endpoint: ${url2.protocol}`);
|
|
9674
|
+
}
|
|
9675
|
+
return url2.toString();
|
|
9676
|
+
}
|
|
9677
|
+
async function keepAgentBaySessionAlive(sessionId) {
|
|
9678
|
+
const session = await requireSession(sessionId, resolveAgentBayApiKey());
|
|
9679
|
+
const result = await session.keepAlive();
|
|
9680
|
+
if (result.success === false) throw new Error(result.errorMessage || "AgentBay keepalive failed");
|
|
9681
|
+
}
|
|
9682
|
+
async function initializeAgentBayBrowserSession(session, input, cookies, options = {}) {
|
|
9683
|
+
const initialized = await session.browser.initializeAsync(
|
|
9684
|
+
options.userAgent ? { userAgent: options.userAgent } : {}
|
|
9685
|
+
);
|
|
9686
|
+
if (!initialized) throw new Error("AgentBay browser initialization failed");
|
|
9687
|
+
const endpoint = await session.browser.getEndpointUrl();
|
|
9688
|
+
const cdp = await (options.connectCdp ?? ((url2) => CdpClient.connect(url2)))(endpoint);
|
|
9689
|
+
try {
|
|
9690
|
+
await cdp.sendCommand("Browser.getVersion", {}, 1e4);
|
|
9691
|
+
const copiedCookieCount = await cdpImportCookiesWithClient(cdp, cookies);
|
|
9692
|
+
if (input.url) {
|
|
9693
|
+
await cdp.sendCommand("Target.createTarget", { url: input.url, background: false });
|
|
9694
|
+
}
|
|
9695
|
+
return copiedCookieCount;
|
|
9696
|
+
} finally {
|
|
9697
|
+
cdp.close();
|
|
9698
|
+
}
|
|
9699
|
+
}
|
|
9700
|
+
async function launchAgentBayBrowser(input, deps) {
|
|
9701
|
+
const name = validateName(input.name);
|
|
9702
|
+
const browserId = agentBayBrowserId(name);
|
|
9703
|
+
validateAgentBayInput(input);
|
|
9704
|
+
const imageId = resolveAgentBayImageId(input.imageId);
|
|
9705
|
+
const userAgentMode = resolveUserAgentMode(input.userAgentMode);
|
|
9706
|
+
const copyCookieDomains = input.copyCookieDomains === void 0 ? [] : normalizeCookieDomains(input.copyCookieDomains);
|
|
9707
|
+
const apiKey = (deps.resolveApiKey ?? resolveAgentBayApiKey)();
|
|
9708
|
+
const releaseLock = acquireLaunchLock(browserId);
|
|
9709
|
+
const persistBrowserRecord = deps.persistBrowserRecord ?? ((record2) => writeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR, record2.browserId), record2));
|
|
9710
|
+
let session = null;
|
|
9711
|
+
let hostPid = 0;
|
|
9712
|
+
let recordWritten = false;
|
|
9713
|
+
try {
|
|
9714
|
+
if (findRecord(browserId)) throw new Error(`AgentBay browser already exists: ${browserId}`);
|
|
9715
|
+
const [cookies, userAgent] = await Promise.all([
|
|
9716
|
+
copyCookieDomains.length > 0 ? deps.exportCookies(copyCookieDomains) : Promise.resolve([]),
|
|
9717
|
+
userAgentMode === "desktop" ? deps.getBrowserUserAgent().then(normalizeDesktopUserAgent) : Promise.resolve(void 0)
|
|
9718
|
+
]);
|
|
9719
|
+
const agentBay = await (deps.createAgentBayClient ?? createClient)(apiKey);
|
|
9720
|
+
const created = await agentBay.create({ imageId, framework: "mearl" });
|
|
9721
|
+
if (!created.success || !created.session) {
|
|
9722
|
+
throw new Error(created.errorMessage || "AgentBay session creation failed");
|
|
9723
|
+
}
|
|
9724
|
+
session = created.session;
|
|
9725
|
+
const copiedCookieCount = await initializeAgentBayBrowserSession(session, input, cookies, {
|
|
9726
|
+
userAgent
|
|
9727
|
+
});
|
|
9728
|
+
const host = spawn4(
|
|
9729
|
+
process.execPath,
|
|
9730
|
+
[
|
|
9731
|
+
deps.nativeHostScript,
|
|
9732
|
+
"--daemon",
|
|
9733
|
+
"--agentbay-session-id",
|
|
9734
|
+
session.sessionId,
|
|
9735
|
+
"--browser-id",
|
|
9736
|
+
browserId,
|
|
9737
|
+
"--browser-name",
|
|
9738
|
+
name
|
|
9739
|
+
],
|
|
9740
|
+
{
|
|
9741
|
+
detached: true,
|
|
9742
|
+
stdio: "ignore",
|
|
9743
|
+
windowsHide: true
|
|
9744
|
+
}
|
|
9745
|
+
);
|
|
9746
|
+
await new Promise((resolveSpawn, rejectSpawn) => {
|
|
9747
|
+
host.once("error", rejectSpawn);
|
|
9748
|
+
host.once("spawn", resolveSpawn);
|
|
9749
|
+
});
|
|
9750
|
+
hostPid = host.pid ?? 0;
|
|
9751
|
+
if (!hostPid) throw new Error("AgentBay native host launched without a process id");
|
|
9752
|
+
host.unref();
|
|
9753
|
+
const accessUrl = normalizeAgentBayAccessUrl(session.resourceUrl);
|
|
9754
|
+
const record2 = {
|
|
9755
|
+
pid: hostPid,
|
|
9756
|
+
browserId,
|
|
9757
|
+
name,
|
|
9758
|
+
sessionId: session.sessionId,
|
|
9759
|
+
imageId,
|
|
9760
|
+
...accessUrl ? { accessUrl } : {},
|
|
9761
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9762
|
+
...copyCookieDomains.length > 0 ? { copiedCookies: { domains: copyCookieDomains, count: copiedCookieCount } } : {}
|
|
9763
|
+
};
|
|
9764
|
+
persistBrowserRecord(record2);
|
|
9765
|
+
recordWritten = true;
|
|
9766
|
+
await waitForBrowserRegistration(browserId, hostPid);
|
|
9767
|
+
deps.log(`AgentBay browser launched: ${browserId}, host=${hostPid}`);
|
|
9768
|
+
return browserSummary2(record2, true);
|
|
9769
|
+
} catch (error48) {
|
|
9770
|
+
if (hostPid) await stopProcess(hostPid, `--browser-id ${browserId}`);
|
|
9771
|
+
if (recordWritten) {
|
|
9772
|
+
removeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR, browserId));
|
|
9773
|
+
removeRecord(keyedConfigFile("browsers", browserId));
|
|
9774
|
+
}
|
|
9775
|
+
if (session) {
|
|
9776
|
+
let cleanupError;
|
|
9777
|
+
try {
|
|
9778
|
+
const deleted = await session.delete(false);
|
|
9779
|
+
if (!deleted.success) {
|
|
9780
|
+
cleanupError = new Error(deleted.errorMessage || "AgentBay session deletion failed");
|
|
9781
|
+
}
|
|
9782
|
+
} catch (deleteError) {
|
|
9783
|
+
cleanupError = deleteError;
|
|
9784
|
+
}
|
|
9785
|
+
if (cleanupError) {
|
|
9786
|
+
const accessUrl = normalizeAgentBayAccessUrl(session.resourceUrl);
|
|
9787
|
+
const recoveryRecord = {
|
|
9788
|
+
pid: hostPid,
|
|
9789
|
+
browserId,
|
|
9790
|
+
name,
|
|
9791
|
+
sessionId: session.sessionId,
|
|
9792
|
+
imageId,
|
|
9793
|
+
...accessUrl ? { accessUrl } : {},
|
|
9794
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
9795
|
+
};
|
|
9796
|
+
let recoverySaved = false;
|
|
9797
|
+
let recoveryError;
|
|
9798
|
+
try {
|
|
9799
|
+
persistBrowserRecord(recoveryRecord);
|
|
9800
|
+
recoverySaved = true;
|
|
9801
|
+
} catch (writeError) {
|
|
9802
|
+
recoveryError = writeError;
|
|
9803
|
+
}
|
|
9804
|
+
deps.log(
|
|
9805
|
+
`AgentBay launch cleanup failed for ${session.sessionId}:`,
|
|
9806
|
+
cleanupError instanceof Error ? cleanupError.message : String(cleanupError)
|
|
9807
|
+
);
|
|
9808
|
+
if (recoveryError) {
|
|
9809
|
+
deps.log(
|
|
9810
|
+
`AgentBay recovery metadata could not be saved for ${session.sessionId}:`,
|
|
9811
|
+
recoveryError instanceof Error ? recoveryError.message : String(recoveryError)
|
|
9812
|
+
);
|
|
9813
|
+
}
|
|
9814
|
+
throw new AggregateError(
|
|
9815
|
+
recoveryError ? [error48, cleanupError, recoveryError] : [error48, cleanupError],
|
|
9816
|
+
`${error48 instanceof Error ? error48.message : String(error48)}; ` + (recoverySaved ? "AgentBay session cleanup failed and recovery metadata was retained for browser_close" : `AgentBay session cleanup failed; session ${session.sessionId} may require manual deletion`),
|
|
9817
|
+
{ cause: error48 }
|
|
9818
|
+
);
|
|
9819
|
+
}
|
|
9820
|
+
}
|
|
9821
|
+
throw error48;
|
|
9822
|
+
} finally {
|
|
9823
|
+
releaseLock();
|
|
9824
|
+
}
|
|
9825
|
+
}
|
|
9826
|
+
function isMissingSessionError(error48) {
|
|
9827
|
+
const message = error48 instanceof Error ? error48.message : String(error48);
|
|
9828
|
+
return /not[ -]?found|does not exist|already deleted|invalid session/i.test(message);
|
|
9829
|
+
}
|
|
9830
|
+
async function closeAgentBayBrowser(selector) {
|
|
9831
|
+
const record2 = findRecord(selector);
|
|
9832
|
+
if (!record2) throw new Error(`AgentBay browser not found: ${selector}`);
|
|
9833
|
+
try {
|
|
9834
|
+
const session = await requireSession(record2.sessionId, resolveAgentBayApiKey());
|
|
9835
|
+
const result = await session.delete(false);
|
|
9836
|
+
if (!result.success) throw new Error(result.errorMessage || "AgentBay session deletion failed");
|
|
9837
|
+
} catch (error48) {
|
|
9838
|
+
if (!isMissingSessionError(error48)) throw error48;
|
|
9839
|
+
}
|
|
9840
|
+
const closingOwnHost = record2.pid === process.pid;
|
|
9841
|
+
if (!closingOwnHost) await stopProcess(record2.pid, `--browser-id ${record2.browserId}`);
|
|
9842
|
+
removeRecord(keyedConfigFile(AGENTBAY_BROWSERS_SUBDIR, record2.browserId));
|
|
9843
|
+
removeRecord(keyedConfigFile("browsers", record2.browserId));
|
|
9844
|
+
if (closingOwnHost) {
|
|
9845
|
+
const timer = setTimeout(() => process.kill(process.pid, "SIGTERM"), 250);
|
|
9846
|
+
timer.unref();
|
|
9847
|
+
}
|
|
9848
|
+
return {
|
|
9849
|
+
browserId: record2.browserId,
|
|
9850
|
+
provider: "agentbay",
|
|
9851
|
+
closed: true,
|
|
9852
|
+
sessionDeleted: true
|
|
9853
|
+
};
|
|
9854
|
+
}
|
|
9855
|
+
|
|
9569
9856
|
// src/browser-registry.ts
|
|
9570
9857
|
var BROWSERS_SUBDIR = "browsers";
|
|
9571
9858
|
var STALE_RECORD_TTL_MS = 5 * 6e4;
|
|
@@ -9715,10 +10002,14 @@ function mergeBrowserInventory(connected, managed) {
|
|
|
9715
10002
|
...connectionFields(record2),
|
|
9716
10003
|
headless: managedBrowser.headless,
|
|
9717
10004
|
persistent: managedBrowser.persistent,
|
|
9718
|
-
|
|
10005
|
+
provider: managedBrowser.provider,
|
|
10006
|
+
..."cdpPort" in managedBrowser ? { cdpPort: managedBrowser.cdpPort } : {},
|
|
10007
|
+
..."agentbaySessionId" in managedBrowser ? { agentbaySessionId: managedBrowser.agentbaySessionId } : {},
|
|
10008
|
+
..."agentbayImageId" in managedBrowser && managedBrowser.agentbayImageId ? { agentbayImageId: managedBrowser.agentbayImageId } : {},
|
|
10009
|
+
..."agentbayAccessUrl" in managedBrowser && managedBrowser.agentbayAccessUrl ? { agentbayAccessUrl: managedBrowser.agentbayAccessUrl } : {},
|
|
9719
10010
|
createdAt: managedBrowser.createdAt,
|
|
9720
|
-
account: managedBrowser.account,
|
|
9721
|
-
copiedCookies: managedBrowser.copiedCookies
|
|
10011
|
+
..."account" in managedBrowser ? { account: managedBrowser.account } : {},
|
|
10012
|
+
..."copiedCookies" in managedBrowser ? { copiedCookies: managedBrowser.copiedCookies } : {}
|
|
9722
10013
|
};
|
|
9723
10014
|
});
|
|
9724
10015
|
const disconnected = [...managedById.values()].sort((a, b) => b.createdAt.localeCompare(a.createdAt)).map((browser) => ({
|
|
@@ -9728,10 +10019,14 @@ function mergeBrowserInventory(connected, managed) {
|
|
|
9728
10019
|
status: browser.running ? "running_disconnected" : "stopped",
|
|
9729
10020
|
headless: browser.headless,
|
|
9730
10021
|
persistent: browser.persistent,
|
|
9731
|
-
|
|
10022
|
+
provider: browser.provider,
|
|
10023
|
+
..."cdpPort" in browser ? { cdpPort: browser.cdpPort } : {},
|
|
10024
|
+
..."agentbaySessionId" in browser ? { agentbaySessionId: browser.agentbaySessionId } : {},
|
|
10025
|
+
..."agentbayImageId" in browser && browser.agentbayImageId ? { agentbayImageId: browser.agentbayImageId } : {},
|
|
10026
|
+
..."agentbayAccessUrl" in browser && browser.agentbayAccessUrl ? { agentbayAccessUrl: browser.agentbayAccessUrl } : {},
|
|
9732
10027
|
createdAt: browser.createdAt,
|
|
9733
|
-
account: browser.account,
|
|
9734
|
-
copiedCookies: browser.copiedCookies
|
|
10028
|
+
..."account" in browser ? { account: browser.account } : {},
|
|
10029
|
+
..."copiedCookies" in browser ? { copiedCookies: browser.copiedCookies } : {}
|
|
9735
10030
|
}));
|
|
9736
10031
|
browsers.push(...disconnected);
|
|
9737
10032
|
return {
|
|
@@ -9741,7 +10036,7 @@ function mergeBrowserInventory(connected, managed) {
|
|
|
9741
10036
|
};
|
|
9742
10037
|
}
|
|
9743
10038
|
function listBrowserInventory() {
|
|
9744
|
-
const managed = listManagedBrowsers();
|
|
10039
|
+
const managed = [...listManagedBrowsers(), ...listAgentBayBrowsers()];
|
|
9745
10040
|
return mergeBrowserInventory(listRegisteredBrowsers(), managed);
|
|
9746
10041
|
}
|
|
9747
10042
|
|
|
@@ -9752,7 +10047,7 @@ import os2 from "node:os";
|
|
|
9752
10047
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
9753
10048
|
|
|
9754
10049
|
// src/version.ts
|
|
9755
|
-
var NATIVE_HOST_VERSION = true ? "2.
|
|
10050
|
+
var NATIVE_HOST_VERSION = true ? "2.5.0" : "unknown";
|
|
9756
10051
|
|
|
9757
10052
|
// src/analytics.ts
|
|
9758
10053
|
var MEASUREMENT_ID = "G-W84LJDZ6PH";
|
|
@@ -9936,14 +10231,14 @@ function selectedPath(stdout) {
|
|
|
9936
10231
|
const value = stdout.replace(/[\r\n]+$/, "");
|
|
9937
10232
|
return value || null;
|
|
9938
10233
|
}
|
|
9939
|
-
var runDirectoryPickerCommand = (command, args) => new Promise((
|
|
10234
|
+
var runDirectoryPickerCommand = (command, args) => new Promise((resolve2, reject) => {
|
|
9940
10235
|
execFile(command, args, { encoding: "utf8", windowsHide: true }, (error48, stdout) => {
|
|
9941
10236
|
if (!error48) {
|
|
9942
|
-
|
|
10237
|
+
resolve2(selectedPath(stdout));
|
|
9943
10238
|
return;
|
|
9944
10239
|
}
|
|
9945
10240
|
if (error48.code === 1) {
|
|
9946
|
-
|
|
10241
|
+
resolve2(null);
|
|
9947
10242
|
return;
|
|
9948
10243
|
}
|
|
9949
10244
|
reject(error48);
|
|
@@ -10614,17 +10909,17 @@ var AgentChatManager = class {
|
|
|
10614
10909
|
// src/agent/codex-provider.ts
|
|
10615
10910
|
import os3 from "node:os";
|
|
10616
10911
|
import readline from "node:readline";
|
|
10617
|
-
import { spawn as
|
|
10912
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
10618
10913
|
|
|
10619
10914
|
// src/agent/executable-resolver.ts
|
|
10620
10915
|
import fs6 from "node:fs";
|
|
10621
|
-
import { spawn as
|
|
10916
|
+
import { spawn as spawn6 } from "node:child_process";
|
|
10622
10917
|
import path7 from "node:path";
|
|
10623
10918
|
|
|
10624
10919
|
// ../setup/dist/process.js
|
|
10625
10920
|
import fs5 from "node:fs";
|
|
10626
10921
|
import path6 from "node:path";
|
|
10627
|
-
import { spawn as
|
|
10922
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
10628
10923
|
var MAX_CAPTURE_LENGTH = 1e6;
|
|
10629
10924
|
function isExecutable(filePath, platform = process.platform) {
|
|
10630
10925
|
try {
|
|
@@ -10686,7 +10981,7 @@ function prependPathDirectory(directory, env = process.env) {
|
|
|
10686
10981
|
function findExecutable(name, options = {}) {
|
|
10687
10982
|
const env = options.env ?? process.env;
|
|
10688
10983
|
const platform = options.platform ?? process.platform;
|
|
10689
|
-
const
|
|
10984
|
+
const existsSync5 = options.existsSync ?? ((candidate) => isExecutable(candidate, platform));
|
|
10690
10985
|
const pathKey = Object.keys(env).find((key) => key.toLowerCase() === "path") || "PATH";
|
|
10691
10986
|
const directories = [
|
|
10692
10987
|
...options.extraDirectories ?? [],
|
|
@@ -10695,16 +10990,16 @@ function findExecutable(name, options = {}) {
|
|
|
10695
10990
|
for (const directory of directories) {
|
|
10696
10991
|
for (const executableName of executableNames(name, platform)) {
|
|
10697
10992
|
const candidate = path6.join(directory, executableName);
|
|
10698
|
-
if (
|
|
10993
|
+
if (existsSync5(candidate))
|
|
10699
10994
|
return candidate;
|
|
10700
10995
|
}
|
|
10701
10996
|
}
|
|
10702
10997
|
return null;
|
|
10703
10998
|
}
|
|
10704
|
-
var runCommand = (command, args, options = {}) => new Promise((
|
|
10999
|
+
var runCommand = (command, args, options = {}) => new Promise((resolve2, reject) => {
|
|
10705
11000
|
const capture = options.capture === true;
|
|
10706
11001
|
const launch = resolveSpawnCommand(command, args);
|
|
10707
|
-
const child =
|
|
11002
|
+
const child = spawn5(launch.command, launch.args, {
|
|
10708
11003
|
cwd: options.cwd,
|
|
10709
11004
|
env: options.env,
|
|
10710
11005
|
stdio: capture ? ["ignore", "pipe", "pipe"] : "inherit",
|
|
@@ -10723,7 +11018,7 @@ var runCommand = (command, args, options = {}) => new Promise((resolve, reject)
|
|
|
10723
11018
|
if (error48)
|
|
10724
11019
|
reject(error48);
|
|
10725
11020
|
else
|
|
10726
|
-
|
|
11021
|
+
resolve2({ code, stdout, stderr });
|
|
10727
11022
|
};
|
|
10728
11023
|
const timer = options.timeoutMs === void 0 ? void 0 : setTimeout(() => {
|
|
10729
11024
|
child.kill("SIGTERM");
|
|
@@ -10845,11 +11140,11 @@ function executableFileCandidates(candidates) {
|
|
|
10845
11140
|
return executableCandidates;
|
|
10846
11141
|
}
|
|
10847
11142
|
function probeAgentExecutable(executable, options) {
|
|
10848
|
-
return new Promise((
|
|
11143
|
+
return new Promise((resolve2) => {
|
|
10849
11144
|
let settled = false;
|
|
10850
11145
|
let stderr = "";
|
|
10851
11146
|
const launch = resolveSpawnCommand(executable, options.args);
|
|
10852
|
-
const child =
|
|
11147
|
+
const child = spawn6(launch.command, launch.args, {
|
|
10853
11148
|
stdio: ["ignore", "ignore", "pipe"],
|
|
10854
11149
|
windowsHide: true,
|
|
10855
11150
|
env: prependNodePath()
|
|
@@ -10858,7 +11153,7 @@ function probeAgentExecutable(executable, options) {
|
|
|
10858
11153
|
if (settled) return;
|
|
10859
11154
|
settled = true;
|
|
10860
11155
|
clearTimeout(timer);
|
|
10861
|
-
|
|
11156
|
+
resolve2(error48);
|
|
10862
11157
|
};
|
|
10863
11158
|
const timer = setTimeout(() => {
|
|
10864
11159
|
child.kill("SIGTERM");
|
|
@@ -10989,13 +11284,13 @@ function externalOpenCommand(url2, platform = process.platform) {
|
|
|
10989
11284
|
}
|
|
10990
11285
|
function openExternalUrl(url2) {
|
|
10991
11286
|
const { command, args } = externalOpenCommand(url2);
|
|
10992
|
-
return new Promise((
|
|
10993
|
-
const child =
|
|
11287
|
+
return new Promise((resolve2, reject) => {
|
|
11288
|
+
const child = spawn7(command, args, { stdio: "ignore", windowsHide: true });
|
|
10994
11289
|
child.once("error", (error48) => {
|
|
10995
11290
|
reject(new Error(`Unable to open Codex App: ${error48.message}`));
|
|
10996
11291
|
});
|
|
10997
11292
|
child.once("close", (code) => {
|
|
10998
|
-
if (code === 0)
|
|
11293
|
+
if (code === 0) resolve2();
|
|
10999
11294
|
else reject(new Error("Unable to open Codex App. Make sure it is installed."));
|
|
11000
11295
|
});
|
|
11001
11296
|
});
|
|
@@ -11162,7 +11457,7 @@ var CodexAgentProvider = class {
|
|
|
11162
11457
|
url: `data:${image.mimeType};base64,${image.data}`
|
|
11163
11458
|
}))
|
|
11164
11459
|
],
|
|
11165
|
-
summary: "
|
|
11460
|
+
summary: "detailed"
|
|
11166
11461
|
});
|
|
11167
11462
|
const turnId = result?.turn?.id;
|
|
11168
11463
|
if (typeof turnId !== "string" || !turnId) {
|
|
@@ -11224,7 +11519,7 @@ var CodexAgentProvider = class {
|
|
|
11224
11519
|
const launch = resolveSpawnCommand(executable, ["app-server", "--listen", "stdio://"]);
|
|
11225
11520
|
const childEnv = prependNodePath();
|
|
11226
11521
|
if (this.mearlSocketPath) childEnv.MEARL_SOCKET_PATH = this.mearlSocketPath;
|
|
11227
|
-
const child =
|
|
11522
|
+
const child = spawn7(launch.command, launch.args, {
|
|
11228
11523
|
stdio: ["pipe", "pipe", "pipe"],
|
|
11229
11524
|
windowsHide: true,
|
|
11230
11525
|
env: childEnv
|
|
@@ -11316,12 +11611,12 @@ var CodexAgentProvider = class {
|
|
|
11316
11611
|
}
|
|
11317
11612
|
request(method, params) {
|
|
11318
11613
|
const id = this.nextRequestId++;
|
|
11319
|
-
return new Promise((
|
|
11614
|
+
return new Promise((resolve2, reject) => {
|
|
11320
11615
|
const timer = setTimeout(() => {
|
|
11321
11616
|
this.pendingRequests.delete(id);
|
|
11322
11617
|
reject(new Error(`Codex request timed out: ${method}`));
|
|
11323
11618
|
}, REQUEST_TIMEOUT_MS);
|
|
11324
|
-
this.pendingRequests.set(id, { resolve, reject, timer });
|
|
11619
|
+
this.pendingRequests.set(id, { resolve: resolve2, reject, timer });
|
|
11325
11620
|
try {
|
|
11326
11621
|
this.write({ id, method, params });
|
|
11327
11622
|
} catch (error48) {
|
|
@@ -11395,7 +11690,7 @@ var CodexAgentProvider = class {
|
|
|
11395
11690
|
import fs7 from "node:fs";
|
|
11396
11691
|
import os4 from "node:os";
|
|
11397
11692
|
import path8 from "node:path";
|
|
11398
|
-
import { spawn as
|
|
11693
|
+
import { spawn as spawn8 } from "node:child_process";
|
|
11399
11694
|
import { Readable, Writable } from "node:stream";
|
|
11400
11695
|
|
|
11401
11696
|
// ../../node_modules/.pnpm/@agentclientprotocol+sdk@1.2.1_zod@4.3.6/node_modules/@agentclientprotocol/sdk/dist/schema/index.js
|
|
@@ -11631,7 +11926,7 @@ __export(external_exports, {
|
|
|
11631
11926
|
object: () => object,
|
|
11632
11927
|
optional: () => optional,
|
|
11633
11928
|
overwrite: () => _overwrite,
|
|
11634
|
-
parse: () =>
|
|
11929
|
+
parse: () => parse3,
|
|
11635
11930
|
parseAsync: () => parseAsync2,
|
|
11636
11931
|
partialRecord: () => partialRecord,
|
|
11637
11932
|
pipe: () => pipe,
|
|
@@ -11950,7 +12245,7 @@ __export(core_exports2, {
|
|
|
11950
12245
|
isValidJWT: () => isValidJWT,
|
|
11951
12246
|
locales: () => locales_exports,
|
|
11952
12247
|
meta: () => meta,
|
|
11953
|
-
parse: () =>
|
|
12248
|
+
parse: () => parse2,
|
|
11954
12249
|
parseAsync: () => parseAsync,
|
|
11955
12250
|
prettifyError: () => prettifyError,
|
|
11956
12251
|
process: () => process2,
|
|
@@ -12873,7 +13168,7 @@ var _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
|
12873
13168
|
}
|
|
12874
13169
|
return result.value;
|
|
12875
13170
|
};
|
|
12876
|
-
var
|
|
13171
|
+
var parse2 = /* @__PURE__ */ _parse($ZodRealError);
|
|
12877
13172
|
var _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
|
12878
13173
|
const ctx = _ctx ? Object.assign(_ctx, { async: true }) : { async: true };
|
|
12879
13174
|
let result = schema._zod.run({ value, issues: [] }, ctx);
|
|
@@ -15546,10 +15841,10 @@ var $ZodFunction = /* @__PURE__ */ $constructor("$ZodFunction", (inst, def) => {
|
|
|
15546
15841
|
throw new Error("implement() must be called with a function");
|
|
15547
15842
|
}
|
|
15548
15843
|
return function(...args) {
|
|
15549
|
-
const parsedArgs = inst._def.input ?
|
|
15844
|
+
const parsedArgs = inst._def.input ? parse2(inst._def.input, args) : args;
|
|
15550
15845
|
const result = Reflect.apply(func, this, parsedArgs);
|
|
15551
15846
|
if (inst._def.output) {
|
|
15552
|
-
return
|
|
15847
|
+
return parse2(inst._def.output, result);
|
|
15553
15848
|
}
|
|
15554
15849
|
return result;
|
|
15555
15850
|
};
|
|
@@ -23598,7 +23893,7 @@ var ZodRealError = $constructor("ZodError", initializer2, {
|
|
|
23598
23893
|
});
|
|
23599
23894
|
|
|
23600
23895
|
// ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/classic/parse.js
|
|
23601
|
-
var
|
|
23896
|
+
var parse3 = /* @__PURE__ */ _parse(ZodRealError);
|
|
23602
23897
|
var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
23603
23898
|
var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
23604
23899
|
var safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
@@ -23641,7 +23936,7 @@ var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
23641
23936
|
reg.add(inst, meta3);
|
|
23642
23937
|
return inst;
|
|
23643
23938
|
});
|
|
23644
|
-
inst.parse = (data, params) =>
|
|
23939
|
+
inst.parse = (data, params) => parse3(inst, data, params, { callee: inst.parse });
|
|
23645
23940
|
inst.safeParse = (data, params) => safeParse2(inst, data, params);
|
|
23646
23941
|
inst.parseAsync = async (data, params) => parseAsync2(inst, data, params, { callee: inst.parseAsync });
|
|
23647
23942
|
inst.safeParseAsync = async (data, params) => safeParseAsync2(inst, data, params);
|
|
@@ -27200,12 +27495,12 @@ var Connection = class {
|
|
|
27200
27495
|
const id = this.nextRequestId++;
|
|
27201
27496
|
let cancel = () => {
|
|
27202
27497
|
};
|
|
27203
|
-
const responsePromise = new Promise((
|
|
27498
|
+
const responsePromise = new Promise((resolve2, reject) => {
|
|
27204
27499
|
const pendingResponse = {
|
|
27205
27500
|
resolve: (response) => {
|
|
27206
27501
|
try {
|
|
27207
27502
|
const value = mapResponse ? mapResponse(response) : response;
|
|
27208
|
-
|
|
27503
|
+
resolve2(value);
|
|
27209
27504
|
} catch (error48) {
|
|
27210
27505
|
reject(error48);
|
|
27211
27506
|
}
|
|
@@ -27283,8 +27578,8 @@ var Connection = class {
|
|
|
27283
27578
|
initialize(stream, handlers) {
|
|
27284
27579
|
this.stream = stream;
|
|
27285
27580
|
this.staticHandlers = handlers;
|
|
27286
|
-
this.closedPromise = new Promise((
|
|
27287
|
-
this.abortController.signal.addEventListener("abort", () =>
|
|
27581
|
+
this.closedPromise = new Promise((resolve2) => {
|
|
27582
|
+
this.abortController.signal.addEventListener("abort", () => resolve2());
|
|
27288
27583
|
});
|
|
27289
27584
|
void this.receive();
|
|
27290
27585
|
}
|
|
@@ -27509,13 +27804,13 @@ var ConnectionBuilder = class {
|
|
|
27509
27804
|
/**
|
|
27510
27805
|
* Adds a typed request handler for one method.
|
|
27511
27806
|
*/
|
|
27512
|
-
onReceiveRequest(method,
|
|
27807
|
+
onReceiveRequest(method, parse4, handler) {
|
|
27513
27808
|
return this.withHandler({
|
|
27514
27809
|
handleMessage: async (message, cx) => {
|
|
27515
27810
|
if (message.kind !== "request" || message.method !== method) {
|
|
27516
27811
|
return Handled.no(message);
|
|
27517
27812
|
}
|
|
27518
|
-
const request =
|
|
27813
|
+
const request = parse4(message.params);
|
|
27519
27814
|
return await handler(request, message.responder, cx) ?? Handled.yes();
|
|
27520
27815
|
},
|
|
27521
27816
|
describe: () => `${this.connectionName ?? "request"}:${method}`
|
|
@@ -27524,13 +27819,13 @@ var ConnectionBuilder = class {
|
|
|
27524
27819
|
/**
|
|
27525
27820
|
* Adds a typed notification handler for one method.
|
|
27526
27821
|
*/
|
|
27527
|
-
onReceiveNotification(method,
|
|
27822
|
+
onReceiveNotification(method, parse4, handler) {
|
|
27528
27823
|
return this.withHandler({
|
|
27529
27824
|
handleMessage: async (message, cx) => {
|
|
27530
27825
|
if (message.kind !== "notification" || message.method !== method) {
|
|
27531
27826
|
return Handled.no(message);
|
|
27532
27827
|
}
|
|
27533
|
-
const notification =
|
|
27828
|
+
const notification = parse4(message.params);
|
|
27534
27829
|
return await handler(notification, cx) ?? Handled.yes();
|
|
27535
27830
|
},
|
|
27536
27831
|
describe: () => `${this.connectionName ?? "notification"}:${method}`
|
|
@@ -28072,8 +28367,8 @@ var AsyncQueue = class {
|
|
|
28072
28367
|
if (this.failed) {
|
|
28073
28368
|
return Promise.reject(this.failure);
|
|
28074
28369
|
}
|
|
28075
|
-
return new Promise((
|
|
28076
|
-
this.waiters.push({ resolve, reject });
|
|
28370
|
+
return new Promise((resolve2, reject) => {
|
|
28371
|
+
this.waiters.push({ resolve: resolve2, reject });
|
|
28077
28372
|
});
|
|
28078
28373
|
}
|
|
28079
28374
|
};
|
|
@@ -29184,7 +29479,7 @@ ${message}` : message;
|
|
|
29184
29479
|
}
|
|
29185
29480
|
const { executable } = resolution;
|
|
29186
29481
|
const launch = resolveSpawnCommand(executable, ["--acp"]);
|
|
29187
|
-
const child =
|
|
29482
|
+
const child = spawn8(launch.command, launch.args, {
|
|
29188
29483
|
stdio: ["pipe", "pipe", "pipe"],
|
|
29189
29484
|
windowsHide: true,
|
|
29190
29485
|
env: prependNodePath()
|
|
@@ -29452,10 +29747,10 @@ ${message}` : message;
|
|
|
29452
29747
|
if (requestId === null) {
|
|
29453
29748
|
return Promise.resolve({ outcome: { outcome: "cancelled" } });
|
|
29454
29749
|
}
|
|
29455
|
-
return new Promise((
|
|
29750
|
+
return new Promise((resolve2) => {
|
|
29456
29751
|
this.pendingPermissions.set(requestId, {
|
|
29457
29752
|
providerSessionId: request.sessionId,
|
|
29458
|
-
resolve
|
|
29753
|
+
resolve: resolve2
|
|
29459
29754
|
});
|
|
29460
29755
|
this.emit({
|
|
29461
29756
|
providerSessionId: request.sessionId,
|
|
@@ -29502,7 +29797,7 @@ ${message}` : message;
|
|
|
29502
29797
|
}
|
|
29503
29798
|
}
|
|
29504
29799
|
withTimeout(promise2, operation) {
|
|
29505
|
-
return new Promise((
|
|
29800
|
+
return new Promise((resolve2, reject) => {
|
|
29506
29801
|
const timer = setTimeout(
|
|
29507
29802
|
() => reject(new Error(`${operation} timed out`)),
|
|
29508
29803
|
REQUEST_TIMEOUT_MS2
|
|
@@ -29510,7 +29805,7 @@ ${message}` : message;
|
|
|
29510
29805
|
promise2.then(
|
|
29511
29806
|
(result) => {
|
|
29512
29807
|
clearTimeout(timer);
|
|
29513
|
-
|
|
29808
|
+
resolve2(result);
|
|
29514
29809
|
},
|
|
29515
29810
|
(error48) => {
|
|
29516
29811
|
clearTimeout(timer);
|
|
@@ -29529,9 +29824,9 @@ ${message}` : message;
|
|
|
29529
29824
|
});
|
|
29530
29825
|
}
|
|
29531
29826
|
runSkillsList(executable, cwd) {
|
|
29532
|
-
return new Promise((
|
|
29827
|
+
return new Promise((resolve2, reject) => {
|
|
29533
29828
|
const launch = resolveSpawnCommand(executable, ["skill", "list", "--all"]);
|
|
29534
|
-
const child =
|
|
29829
|
+
const child = spawn8(launch.command, launch.args, {
|
|
29535
29830
|
cwd,
|
|
29536
29831
|
stdio: ["ignore", "pipe", "pipe"],
|
|
29537
29832
|
windowsHide: true,
|
|
@@ -29545,7 +29840,7 @@ ${message}` : message;
|
|
|
29545
29840
|
settled = true;
|
|
29546
29841
|
clearTimeout(timer);
|
|
29547
29842
|
if (error48) reject(error48);
|
|
29548
|
-
else
|
|
29843
|
+
else resolve2(stdout);
|
|
29549
29844
|
};
|
|
29550
29845
|
const timer = setTimeout(() => {
|
|
29551
29846
|
child.kill("SIGTERM");
|
|
@@ -29580,12 +29875,12 @@ ${message}` : message;
|
|
|
29580
29875
|
import fs8 from "node:fs";
|
|
29581
29876
|
import os5 from "node:os";
|
|
29582
29877
|
import path9 from "node:path";
|
|
29583
|
-
import { spawn as
|
|
29878
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
29584
29879
|
var COMMAND_TIMEOUT_MS = 12e4;
|
|
29585
29880
|
var MAX_OUTPUT_LENGTH = 1e6;
|
|
29586
29881
|
var ANSI_ESCAPE_PATTERN = new RegExp(String.raw`\u001B\[[0-?]*[ -/]*[@-~]`, "g");
|
|
29587
|
-
function existingExecutable(candidates,
|
|
29588
|
-
return candidates.find((candidate) => candidate &&
|
|
29882
|
+
function existingExecutable(candidates, existsSync5) {
|
|
29883
|
+
return candidates.find((candidate) => candidate && existsSync5(candidate)) ?? null;
|
|
29589
29884
|
}
|
|
29590
29885
|
function stripAnsi(value) {
|
|
29591
29886
|
return value.replace(ANSI_ESCAPE_PATTERN, "");
|
|
@@ -29594,7 +29889,7 @@ function resolveAliSkillsExecutable(options = {}) {
|
|
|
29594
29889
|
const env = options.env ?? process.env;
|
|
29595
29890
|
const home = (options.homedir ?? os5.homedir)();
|
|
29596
29891
|
const platform = options.platform ?? process.platform;
|
|
29597
|
-
const
|
|
29892
|
+
const existsSync5 = options.existsSync ?? ((candidate) => isExecutable(candidate, platform));
|
|
29598
29893
|
const processExecPath = options.processExecPath ?? process.execPath;
|
|
29599
29894
|
const readdirSync2 = options.readdirSync ?? fs8.readdirSync;
|
|
29600
29895
|
const names = executableNames("ali-skills", platform);
|
|
@@ -29616,11 +29911,11 @@ function resolveAliSkillsExecutable(options = {}) {
|
|
|
29616
29911
|
...platform === "win32" ? [] : ["/opt/homebrew/bin/ali-skills", "/usr/local/bin/ali-skills", "/usr/bin/ali-skills"],
|
|
29617
29912
|
...pathCandidates
|
|
29618
29913
|
];
|
|
29619
|
-
return existingExecutable(candidates,
|
|
29914
|
+
return existingExecutable(candidates, existsSync5);
|
|
29620
29915
|
}
|
|
29621
|
-
var runAliSkillsCli = (executable, args, cwd) => new Promise((
|
|
29916
|
+
var runAliSkillsCli = (executable, args, cwd) => new Promise((resolve2, reject) => {
|
|
29622
29917
|
const launch = resolveSpawnCommand(executable, args);
|
|
29623
|
-
const child =
|
|
29918
|
+
const child = spawn9(launch.command, launch.args, {
|
|
29624
29919
|
cwd,
|
|
29625
29920
|
env: prependNodePath(prependCommandPath(executable)),
|
|
29626
29921
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -29638,7 +29933,7 @@ var runAliSkillsCli = (executable, args, cwd) => new Promise((resolve, reject) =
|
|
|
29638
29933
|
if (error48)
|
|
29639
29934
|
reject(error48);
|
|
29640
29935
|
else
|
|
29641
|
-
|
|
29936
|
+
resolve2({ stdout, stderr });
|
|
29642
29937
|
};
|
|
29643
29938
|
const timer = setTimeout(() => {
|
|
29644
29939
|
child.kill("SIGTERM");
|
|
@@ -29826,7 +30121,7 @@ function createExtensionRequestMessage(id, action, data, trustedInternal = false
|
|
|
29826
30121
|
// src/host-updater.ts
|
|
29827
30122
|
import fs10 from "node:fs";
|
|
29828
30123
|
import path11 from "node:path";
|
|
29829
|
-
import { fileURLToPath } from "node:url";
|
|
30124
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
29830
30125
|
|
|
29831
30126
|
// ../setup/dist/packageManager.js
|
|
29832
30127
|
import fs9 from "node:fs";
|
|
@@ -29834,8 +30129,8 @@ import path10 from "node:path";
|
|
|
29834
30129
|
function normalizePath(filePath) {
|
|
29835
30130
|
return filePath.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
29836
30131
|
}
|
|
29837
|
-
function firstExisting(candidates,
|
|
29838
|
-
return candidates.find((candidate) =>
|
|
30132
|
+
function firstExisting(candidates, existsSync5) {
|
|
30133
|
+
return candidates.find((candidate) => existsSync5(candidate));
|
|
29839
30134
|
}
|
|
29840
30135
|
function fallbackCommand(name, platform) {
|
|
29841
30136
|
if (platform !== "win32")
|
|
@@ -29847,7 +30142,7 @@ function fallbackCommand(name, platform) {
|
|
|
29847
30142
|
function resolvePackageManagerInstallation(packageRoot, packageName, options = {}) {
|
|
29848
30143
|
const env = options.env ?? process.env;
|
|
29849
30144
|
const platform = options.platform ?? process.platform;
|
|
29850
|
-
const
|
|
30145
|
+
const existsSync5 = options.existsSync ?? ((candidate) => isExecutable(candidate, platform));
|
|
29851
30146
|
const processExecPath = options.processExecPath ?? process.execPath;
|
|
29852
30147
|
const normalizedRoot = normalizePath(path10.resolve(packageRoot));
|
|
29853
30148
|
const lowerRoot = normalizedRoot.toLowerCase();
|
|
@@ -29858,13 +30153,13 @@ function resolvePackageManagerInstallation(packageRoot, packageName, options = {
|
|
|
29858
30153
|
const command = firstExisting([
|
|
29859
30154
|
...executableNames("pnpm", platform).map((name) => path10.join(pnpmHome, name)),
|
|
29860
30155
|
...executableNames("pnpm", platform).map((name) => path10.join(path10.dirname(processExecPath), name))
|
|
29861
|
-
],
|
|
30156
|
+
], existsSync5) ?? fallbackCommand("pnpm", platform);
|
|
29862
30157
|
return { manager: "pnpm", command, binDirectory: pnpmHome };
|
|
29863
30158
|
}
|
|
29864
30159
|
const bunMarker = `/.bun/install/global/node_modules/${lowerPackageName}`;
|
|
29865
30160
|
if (lowerRoot.endsWith(bunMarker)) {
|
|
29866
30161
|
const bunHome = normalizedRoot.slice(0, lowerRoot.indexOf("/.bun/"));
|
|
29867
|
-
const command = firstExisting(executableNames("bun", platform).map((name) => path10.join(bunHome, ".bun", "bin", name)),
|
|
30162
|
+
const command = firstExisting(executableNames("bun", platform).map((name) => path10.join(bunHome, ".bun", "bin", name)), existsSync5) ?? fallbackCommand("bun", platform);
|
|
29868
30163
|
return {
|
|
29869
30164
|
manager: "bun",
|
|
29870
30165
|
command,
|
|
@@ -29883,12 +30178,12 @@ function resolvePackageManagerInstallation(packageRoot, packageName, options = {
|
|
|
29883
30178
|
const command = firstExisting([
|
|
29884
30179
|
...executableNames("yarn", platform).map((name) => path10.join(binDirectory, name)),
|
|
29885
30180
|
...executableNames("yarn", platform).map((name) => path10.join(path10.dirname(processExecPath), name))
|
|
29886
|
-
],
|
|
30181
|
+
], existsSync5) ?? findExecutable("yarn", { env, existsSync: existsSync5, platform }) ?? fallbackCommand("yarn", platform);
|
|
29887
30182
|
return { manager: "yarn", command, binDirectory };
|
|
29888
30183
|
}
|
|
29889
30184
|
if (lowerRoot.includes("/.volta/tools/image/packages/") && lowerRoot.endsWith(`/lib/node_modules/${lowerPackageName}`)) {
|
|
29890
30185
|
const voltaHome = normalizedRoot.slice(0, lowerRoot.indexOf("/.volta/"));
|
|
29891
|
-
const command = firstExisting(executableNames("volta", platform).map((name) => path10.join(voltaHome, ".volta", "bin", name)),
|
|
30186
|
+
const command = firstExisting(executableNames("volta", platform).map((name) => path10.join(voltaHome, ".volta", "bin", name)), existsSync5) ?? fallbackCommand("volta", platform);
|
|
29892
30187
|
return {
|
|
29893
30188
|
manager: "volta",
|
|
29894
30189
|
command,
|
|
@@ -29901,7 +30196,7 @@ function resolvePackageManagerInstallation(packageRoot, packageName, options = {
|
|
|
29901
30196
|
const command = firstExisting([
|
|
29902
30197
|
...executableNames("npm", platform).map((name) => path10.join(prefix, "bin", name)),
|
|
29903
30198
|
...executableNames("npm", platform).map((name) => path10.join(path10.dirname(processExecPath), name))
|
|
29904
|
-
],
|
|
30199
|
+
], existsSync5) ?? fallbackCommand("npm", platform);
|
|
29905
30200
|
return { manager: "npm", command, binDirectory: path10.join(prefix, "bin") };
|
|
29906
30201
|
}
|
|
29907
30202
|
if (platform === "win32" && env.APPDATA) {
|
|
@@ -29911,7 +30206,7 @@ function resolvePackageManagerInstallation(packageRoot, packageName, options = {
|
|
|
29911
30206
|
const command = firstExisting([
|
|
29912
30207
|
...executableNames("npm", platform).map((name) => path10.join(binDirectory, name)),
|
|
29913
30208
|
...executableNames("npm", platform).map((name) => path10.join(path10.dirname(processExecPath), name))
|
|
29914
|
-
],
|
|
30209
|
+
], existsSync5) ?? fallbackCommand("npm", platform);
|
|
29915
30210
|
return { manager: "npm", command, binDirectory };
|
|
29916
30211
|
}
|
|
29917
30212
|
}
|
|
@@ -30002,7 +30297,7 @@ var NativeHostUpdateFailure = class extends Error {
|
|
|
30002
30297
|
}
|
|
30003
30298
|
};
|
|
30004
30299
|
function wait(delayMs) {
|
|
30005
|
-
return new Promise((
|
|
30300
|
+
return new Promise((resolve2) => setTimeout(resolve2, delayMs));
|
|
30006
30301
|
}
|
|
30007
30302
|
function readLockState(lockPath) {
|
|
30008
30303
|
try {
|
|
@@ -30115,7 +30410,7 @@ function currentNativeHostPackageRoot(entryPath) {
|
|
|
30115
30410
|
return null;
|
|
30116
30411
|
}
|
|
30117
30412
|
function currentPackageManagerInstallation(environment, nodePath, platform) {
|
|
30118
|
-
const packageRoot = currentNativeHostPackageRoot(
|
|
30413
|
+
const packageRoot = currentNativeHostPackageRoot(fileURLToPath2(import.meta.url));
|
|
30119
30414
|
if (!packageRoot) return null;
|
|
30120
30415
|
return resolvePackageManagerInstallation(packageRoot, "@mearl/native-host", {
|
|
30121
30416
|
env: environment,
|
|
@@ -30245,6 +30540,7 @@ function positivePort(value, fallback) {
|
|
|
30245
30540
|
}
|
|
30246
30541
|
var CDP_PORT = positivePort(cliOption("--cdp-port"), 9222);
|
|
30247
30542
|
var CDP_USER_DATA_DIR = cliOption("--cdp-user-data-dir");
|
|
30543
|
+
var AGENTBAY_SESSION_ID = cliOption("--agentbay-session-id");
|
|
30248
30544
|
var CDP_BROWSER_ID = cliOption("--browser-id") ?? "cdp";
|
|
30249
30545
|
var CDP_BROWSER_NAME = cliOption("--browser-name") ?? "CDP";
|
|
30250
30546
|
if (cliArg === "--init" || cliArg === "--uninstall") {
|
|
@@ -30271,6 +30567,7 @@ Options:
|
|
|
30271
30567
|
--daemon Start as standalone CDP daemon (no extension needed)
|
|
30272
30568
|
--cdp-port <port> CDP port for daemon mode (default 9222)
|
|
30273
30569
|
--cdp-user-data-dir <dir> Read DevToolsActivePort from this Chrome profile
|
|
30570
|
+
--agentbay-session-id <id> Connect to an AgentBay browser session over CDP
|
|
30274
30571
|
--browser-id <id> Registry id for this CDP browser
|
|
30275
30572
|
--browser-name <name> Human-readable registry name
|
|
30276
30573
|
--version, -v Show version
|
|
@@ -30314,28 +30611,53 @@ function extractChromeVersion(input) {
|
|
|
30314
30611
|
const parts = match[1].split(".");
|
|
30315
30612
|
return parts.slice(0, 3).join(".");
|
|
30316
30613
|
}
|
|
30317
|
-
function fetchCdpBrowserVersion() {
|
|
30614
|
+
async function fetchCdpBrowserVersion() {
|
|
30615
|
+
if (AGENTBAY_SESSION_ID) {
|
|
30616
|
+
try {
|
|
30617
|
+
const browser = await getCdpSession().getBrowserClient();
|
|
30618
|
+
const result = await browser.sendCommand("Browser.getVersion", {}, 5e3);
|
|
30619
|
+
return result.product ?? null;
|
|
30620
|
+
} catch {
|
|
30621
|
+
return null;
|
|
30622
|
+
}
|
|
30623
|
+
}
|
|
30318
30624
|
const port = readDevToolsActivePort(CDP_USER_DATA_DIR)?.port ?? CDP_PORT;
|
|
30319
|
-
return new Promise((
|
|
30320
|
-
const req =
|
|
30625
|
+
return new Promise((resolve2) => {
|
|
30626
|
+
const req = http4.get(`http://localhost:${port}/json/version`, (res) => {
|
|
30321
30627
|
let data = "";
|
|
30322
30628
|
res.on("data", (chunk) => data += chunk);
|
|
30323
30629
|
res.on("end", () => {
|
|
30324
30630
|
try {
|
|
30325
30631
|
const info = JSON.parse(data);
|
|
30326
|
-
|
|
30632
|
+
resolve2(info.Browser ?? null);
|
|
30327
30633
|
} catch {
|
|
30328
|
-
|
|
30634
|
+
resolve2(null);
|
|
30329
30635
|
}
|
|
30330
30636
|
});
|
|
30331
30637
|
});
|
|
30332
|
-
req.on("error", () =>
|
|
30638
|
+
req.on("error", () => resolve2(null));
|
|
30333
30639
|
req.setTimeout(2e3, () => {
|
|
30334
30640
|
req.destroy();
|
|
30335
|
-
|
|
30641
|
+
resolve2(null);
|
|
30336
30642
|
});
|
|
30337
30643
|
});
|
|
30338
30644
|
}
|
|
30645
|
+
async function getCurrentBrowserUserAgent() {
|
|
30646
|
+
if (extensionVersion !== null) {
|
|
30647
|
+
try {
|
|
30648
|
+
const result = await sendRequestToExtension("get_browser_info", {}, 3e3);
|
|
30649
|
+
if (result.userAgent?.trim()) return result.userAgent;
|
|
30650
|
+
} catch {
|
|
30651
|
+
}
|
|
30652
|
+
}
|
|
30653
|
+
try {
|
|
30654
|
+
const browser = await getCdpSession().getBrowserClient();
|
|
30655
|
+
const result = await browser.sendCommand("Browser.getVersion", {}, 5e3);
|
|
30656
|
+
if (result.userAgent?.trim()) return result.userAgent;
|
|
30657
|
+
} catch {
|
|
30658
|
+
}
|
|
30659
|
+
throw new Error("Could not determine the control browser user agent for userAgentMode=desktop");
|
|
30660
|
+
}
|
|
30339
30661
|
async function collectVersions() {
|
|
30340
30662
|
const info = {
|
|
30341
30663
|
nativeHost: NATIVE_HOST_VERSION,
|
|
@@ -30387,7 +30709,9 @@ function scheduleInventoryExit() {
|
|
|
30387
30709
|
var cdpSession = null;
|
|
30388
30710
|
function getCdpSession() {
|
|
30389
30711
|
if (!cdpSession) {
|
|
30390
|
-
cdpSession = new CdpSession({
|
|
30712
|
+
cdpSession = AGENTBAY_SESSION_ID ? new CdpSession({
|
|
30713
|
+
endpointResolver: () => resolveAgentBayEndpoint(AGENTBAY_SESSION_ID)
|
|
30714
|
+
}) : new CdpSession({ port: CDP_PORT, userDataDir: CDP_USER_DATA_DIR });
|
|
30391
30715
|
}
|
|
30392
30716
|
return cdpSession;
|
|
30393
30717
|
}
|
|
@@ -30591,12 +30915,12 @@ function setupNativeMessageInput() {
|
|
|
30591
30915
|
}
|
|
30592
30916
|
function sendRequestToExtension(action, data, timeoutMs, trustedInternal = false, controlSource = "local") {
|
|
30593
30917
|
const id = `${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
|
|
30594
|
-
return new Promise((
|
|
30918
|
+
return new Promise((resolve2, reject) => {
|
|
30595
30919
|
const timer = setTimeout(() => {
|
|
30596
30920
|
pendingRequests.delete(id);
|
|
30597
30921
|
reject(new Error(`Request timeout after ${timeoutMs}ms`));
|
|
30598
30922
|
}, timeoutMs);
|
|
30599
|
-
pendingRequests.set(id, { resolve, reject, timer });
|
|
30923
|
+
pendingRequests.set(id, { resolve: resolve2, reject, timer });
|
|
30600
30924
|
sendToExtension(
|
|
30601
30925
|
createExtensionRequestMessage(id, action, data, trustedInternal, controlSource)
|
|
30602
30926
|
);
|
|
@@ -30706,7 +31030,14 @@ async function handleSocketLine(socket, line) {
|
|
|
30706
31030
|
try {
|
|
30707
31031
|
const selector = String(data?.browser ?? data?.browserId ?? data?.name ?? "").trim();
|
|
30708
31032
|
if (!selector) throw new Error("browser is required");
|
|
30709
|
-
const
|
|
31033
|
+
const localExists = hasManagedBrowser(selector);
|
|
31034
|
+
const agentBayExists = hasAgentBayBrowser(selector);
|
|
31035
|
+
if (localExists && agentBayExists) {
|
|
31036
|
+
throw new Error(
|
|
31037
|
+
`Managed browser name is ambiguous: ${selector}. Use the full browserId from browser_list.`
|
|
31038
|
+
);
|
|
31039
|
+
}
|
|
31040
|
+
const result = agentBayExists ? await closeAgentBayBrowser(selector) : await closeManagedBrowser(selector, { deleteProfile: data?.deleteProfile });
|
|
30710
31041
|
socket.write(JSON.stringify({ id, success: true, data: result }) + "\n");
|
|
30711
31042
|
} catch (error48) {
|
|
30712
31043
|
socket.write(
|
|
@@ -30798,7 +31129,6 @@ async function handleSocketLine(socket, line) {
|
|
|
30798
31129
|
}
|
|
30799
31130
|
if (action === "browser_launch") {
|
|
30800
31131
|
try {
|
|
30801
|
-
const prepareTdbankSso = extensionVersion !== null ? (payload) => sendRequestToExtension("__tdbank_prepare_sso", payload, 2e4, true) : (payload) => cdpPrepareTdbankSso(getCdpSession(), payload);
|
|
30802
31132
|
const exportCookies = extensionVersion !== null ? async (domains) => {
|
|
30803
31133
|
const result2 = await sendRequestToExtension(
|
|
30804
31134
|
"__export_cookies",
|
|
@@ -30808,8 +31138,34 @@ async function handleSocketLine(socket, line) {
|
|
|
30808
31138
|
);
|
|
30809
31139
|
return result2.cookies ?? [];
|
|
30810
31140
|
} : (domains) => cdpExportCookies(getCdpSession(), domains);
|
|
31141
|
+
if (data?.provider === "agentbay") {
|
|
31142
|
+
const name2 = typeof data?.name === "string" ? data.name.trim() : "";
|
|
31143
|
+
if (name2 && hasManagedBrowser(name2)) {
|
|
31144
|
+
throw new Error(
|
|
31145
|
+
`Managed browser name is already used by the local provider: ${name2}. Choose a unique name.`
|
|
31146
|
+
);
|
|
31147
|
+
}
|
|
31148
|
+
const result2 = await launchAgentBayBrowser(data, {
|
|
31149
|
+
nativeHostScript: fileURLToPath4(import.meta.url),
|
|
31150
|
+
exportCookies,
|
|
31151
|
+
getBrowserUserAgent: getCurrentBrowserUserAgent,
|
|
31152
|
+
log
|
|
31153
|
+
});
|
|
31154
|
+
socket.write(JSON.stringify({ id, success: true, data: result2 }) + "\n");
|
|
31155
|
+
return;
|
|
31156
|
+
}
|
|
31157
|
+
if (data?.provider !== void 0 && data.provider !== "local") {
|
|
31158
|
+
throw new Error('provider must be "local" or "agentbay"');
|
|
31159
|
+
}
|
|
31160
|
+
const name = typeof data?.name === "string" ? data.name.trim() : "";
|
|
31161
|
+
if (name && hasAgentBayBrowser(name)) {
|
|
31162
|
+
throw new Error(
|
|
31163
|
+
`Managed browser name is already used by the AgentBay provider: ${name}. Choose a unique name.`
|
|
31164
|
+
);
|
|
31165
|
+
}
|
|
31166
|
+
const prepareTdbankSso = extensionVersion !== null ? (payload) => sendRequestToExtension("__tdbank_prepare_sso", payload, 2e4, true) : (payload) => cdpPrepareTdbankSso(getCdpSession(), payload);
|
|
30811
31167
|
const result = await launchManagedBrowser(data, {
|
|
30812
|
-
nativeHostScript:
|
|
31168
|
+
nativeHostScript: fileURLToPath4(import.meta.url),
|
|
30813
31169
|
prepareTdbankSso,
|
|
30814
31170
|
exportCookies,
|
|
30815
31171
|
log
|
|
@@ -30901,8 +31257,21 @@ async function handleViaCdp(action, data, _timeoutMs, controlSource) {
|
|
|
30901
31257
|
`${action} requires the Mearl browser extension. Install it from https://chromewebstore.google.com/detail/mearl/aoehhjnofngknnjefamjbplchbolghkm`
|
|
30902
31258
|
);
|
|
30903
31259
|
}
|
|
30904
|
-
|
|
31260
|
+
if (AGENTBAY_SESSION_ID && action === "page_upload") {
|
|
31261
|
+
throw new Error(
|
|
31262
|
+
"page_upload is not available for AgentBay CDP sessions because file paths resolve on the remote browser host."
|
|
31263
|
+
);
|
|
31264
|
+
}
|
|
31265
|
+
const available = AGENTBAY_SESSION_ID ? await getCdpSession().getBrowserClient().then(
|
|
31266
|
+
() => true,
|
|
31267
|
+
() => false
|
|
31268
|
+
) : await isCdpAvailable(CDP_PORT, CDP_USER_DATA_DIR);
|
|
30905
31269
|
if (!available) {
|
|
31270
|
+
if (AGENTBAY_SESSION_ID) {
|
|
31271
|
+
throw new Error(
|
|
31272
|
+
`AgentBay CDP endpoint is not available for session ${AGENTBAY_SESSION_ID}. Check the session status and AgentBay plan permissions.`
|
|
31273
|
+
);
|
|
31274
|
+
}
|
|
30906
31275
|
throw new Error(
|
|
30907
31276
|
`Chrome DevTools remote debugging is not available on port ${CDP_PORT}. Enable it via chrome://inspect/#remote-debugging (Chrome 145+) or install the Mearl extension.`
|
|
30908
31277
|
);
|
|
@@ -30937,16 +31306,16 @@ function onSocketConnection(socket) {
|
|
|
30937
31306
|
});
|
|
30938
31307
|
}
|
|
30939
31308
|
function isPathAlive(socketPath) {
|
|
30940
|
-
return new Promise((
|
|
31309
|
+
return new Promise((resolve2) => {
|
|
30941
31310
|
if (process.platform !== "win32" && !fs13.existsSync(socketPath)) {
|
|
30942
|
-
|
|
31311
|
+
resolve2(false);
|
|
30943
31312
|
return;
|
|
30944
31313
|
}
|
|
30945
31314
|
const client2 = net.createConnection(socketPath);
|
|
30946
31315
|
const done = (alive) => {
|
|
30947
31316
|
client2.removeAllListeners();
|
|
30948
31317
|
client2.destroy();
|
|
30949
|
-
|
|
31318
|
+
resolve2(alive);
|
|
30950
31319
|
};
|
|
30951
31320
|
const timer = setTimeout(() => done(false), 500);
|
|
30952
31321
|
client2.on("connect", () => {
|
|
@@ -30960,7 +31329,7 @@ function isPathAlive(socketPath) {
|
|
|
30960
31329
|
});
|
|
30961
31330
|
}
|
|
30962
31331
|
function listenOn(socketPath) {
|
|
30963
|
-
return new Promise((
|
|
31332
|
+
return new Promise((resolve2, reject) => {
|
|
30964
31333
|
if (process.platform !== "win32" && fs13.existsSync(socketPath)) {
|
|
30965
31334
|
try {
|
|
30966
31335
|
fs13.unlinkSync(socketPath);
|
|
@@ -30986,7 +31355,7 @@ function listenOn(socketPath) {
|
|
|
30986
31355
|
server.removeListener("error", reject);
|
|
30987
31356
|
server.on("error", (error48) => log("socket server error:", String(error48)));
|
|
30988
31357
|
log(`listening on ${socketPath}`);
|
|
30989
|
-
|
|
31358
|
+
resolve2(server);
|
|
30990
31359
|
});
|
|
30991
31360
|
});
|
|
30992
31361
|
}
|
|
@@ -31087,6 +31456,17 @@ async function main() {
|
|
|
31087
31456
|
lastFocusedAt: CDP_BROWSER_ID.startsWith("managed:") ? 0 : void 0
|
|
31088
31457
|
});
|
|
31089
31458
|
}
|
|
31459
|
+
if (AGENTBAY_SESSION_ID) {
|
|
31460
|
+
const keepAliveTimer = setInterval(() => {
|
|
31461
|
+
keepAgentBaySessionAlive(AGENTBAY_SESSION_ID).catch((error48) => {
|
|
31462
|
+
log(
|
|
31463
|
+
`AgentBay keepalive failed for ${AGENTBAY_SESSION_ID}:`,
|
|
31464
|
+
error48 instanceof Error ? error48.message : String(error48)
|
|
31465
|
+
);
|
|
31466
|
+
});
|
|
31467
|
+
}, 6e4);
|
|
31468
|
+
keepAliveTimer.unref();
|
|
31469
|
+
}
|
|
31090
31470
|
process.on("SIGINT", () => cleanupAndExit(0));
|
|
31091
31471
|
process.on("SIGTERM", () => cleanupAndExit(0));
|
|
31092
31472
|
process.on("uncaughtException", (error48) => {
|