@mearl/native-host 2.2.2 → 2.3.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/agent/codex-provider.d.ts +9 -0
- package/dist/agent/executable-resolver.d.ts +12 -0
- package/dist/agent/process-env.d.ts +1 -1
- package/dist/agent/qoder-provider.d.ts +10 -0
- package/dist/cdp-backend/buffers.d.ts +9 -4
- package/dist/cdp-backend/cdp-session.d.ts +1 -0
- package/dist/cdp-backend/composite-handlers.d.ts +4 -5
- package/dist/cdp-backend/request-handlers.d.ts +3 -1
- package/dist/index.js +621 -242
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -325,7 +325,7 @@ import http3 from "node:http";
|
|
|
325
325
|
|
|
326
326
|
// src/cdp-backend/client.ts
|
|
327
327
|
import http from "node:http";
|
|
328
|
-
import
|
|
328
|
+
import crypto2 from "node:crypto";
|
|
329
329
|
var CdpChildSession = class {
|
|
330
330
|
constructor(parent, sessionId) {
|
|
331
331
|
this.parent = parent;
|
|
@@ -406,8 +406,8 @@ var CdpClient = class _CdpClient {
|
|
|
406
406
|
return new Promise((resolve, reject) => {
|
|
407
407
|
const url2 = new URL(wsUrl);
|
|
408
408
|
const port = parseInt(url2.port || "9222", 10);
|
|
409
|
-
const key =
|
|
410
|
-
const expectedAccept =
|
|
409
|
+
const key = crypto2.randomBytes(16).toString("base64");
|
|
410
|
+
const expectedAccept = crypto2.createHash("sha1").update(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").digest("base64");
|
|
411
411
|
const req = http.request({
|
|
412
412
|
host: url2.hostname,
|
|
413
413
|
port,
|
|
@@ -559,7 +559,7 @@ var CdpClient = class _CdpClient {
|
|
|
559
559
|
sendText(text) {
|
|
560
560
|
if (this._closed) return;
|
|
561
561
|
const payload = Buffer.from(text, "utf-8");
|
|
562
|
-
const maskKey =
|
|
562
|
+
const maskKey = crypto2.randomBytes(4);
|
|
563
563
|
const masked = Buffer.from(payload.map((b, i) => b ^ maskKey[i % 4]));
|
|
564
564
|
let header;
|
|
565
565
|
if (payload.length < 126) {
|
|
@@ -754,6 +754,9 @@ function buildCookieHeaderValue(cookieMap) {
|
|
|
754
754
|
var APLUS_URL_PATTERN = /\.mmstat\.com\//;
|
|
755
755
|
var RUM_URL_PATTERN = /\.rum\.aliyuncs\.com\//;
|
|
756
756
|
var ARMS_URL_PATTERN = /arms-retcode\.aliyuncs\.com\//;
|
|
757
|
+
function isTrackingUrl(url2) {
|
|
758
|
+
return APLUS_URL_PATTERN.test(url2) || RUM_URL_PATTERN.test(url2) || ARMS_URL_PATTERN.test(url2) || /retcode\.alicdn\.com|beacon\.taobao\.com|tbsec\./i.test(url2);
|
|
759
|
+
}
|
|
757
760
|
var aplusCounter = 0;
|
|
758
761
|
var armsCounter = 0;
|
|
759
762
|
var rumCounter = 0;
|
|
@@ -1287,7 +1290,11 @@ function serializeRequest(request, options = {}) {
|
|
|
1287
1290
|
status: request.status,
|
|
1288
1291
|
statusText: request.statusText,
|
|
1289
1292
|
queryString: request.queryString,
|
|
1290
|
-
duration: request.duration
|
|
1293
|
+
duration: request.duration,
|
|
1294
|
+
captureSequence: request.captureSequence,
|
|
1295
|
+
isPending: request.isPending,
|
|
1296
|
+
source: request.source,
|
|
1297
|
+
resourceType: request.resourceType
|
|
1291
1298
|
};
|
|
1292
1299
|
if (includeHeaders) {
|
|
1293
1300
|
result.headers = request.headers;
|
|
@@ -1411,10 +1418,14 @@ function applyFieldLimits(request, maxFieldBytes) {
|
|
|
1411
1418
|
request.responseBody = limitBufferedField(request.responseBody, maxFieldBytes);
|
|
1412
1419
|
}
|
|
1413
1420
|
function trimRequestBuffer(requests, accounting, maxEntries, maxBytes) {
|
|
1421
|
+
const removed = [];
|
|
1414
1422
|
while (requests.length > 1 && (requests.length > maxEntries || accounting.totalBytes > maxBytes)) {
|
|
1415
|
-
requests.shift();
|
|
1423
|
+
const request = requests.shift();
|
|
1424
|
+
if (request)
|
|
1425
|
+
removed.push(request);
|
|
1416
1426
|
accounting.totalBytes -= accounting.sizes.shift() ?? 0;
|
|
1417
1427
|
}
|
|
1428
|
+
return removed;
|
|
1418
1429
|
}
|
|
1419
1430
|
function appendRequestToBuffer(requests, accounting, request, limits = {}) {
|
|
1420
1431
|
const { maxEntries = REQUEST_BUFFER_MAX_ENTRIES, maxBytes = REQUEST_BUFFER_MAX_BYTES, maxFieldBytes = REQUEST_BUFFER_MAX_FIELD_BYTES } = limits;
|
|
@@ -1424,20 +1435,20 @@ function appendRequestToBuffer(requests, accounting, request, limits = {}) {
|
|
|
1424
1435
|
requests.push(request);
|
|
1425
1436
|
accounting.sizes.push(size);
|
|
1426
1437
|
accounting.totalBytes += size;
|
|
1427
|
-
trimRequestBuffer(requests, accounting, maxEntries, maxBytes);
|
|
1438
|
+
return trimRequestBuffer(requests, accounting, maxEntries, maxBytes);
|
|
1428
1439
|
}
|
|
1429
1440
|
function refreshRequestInBuffer(requests, accounting, request, limits = {}) {
|
|
1430
1441
|
const { maxEntries = REQUEST_BUFFER_MAX_ENTRIES, maxBytes = REQUEST_BUFFER_MAX_BYTES, maxFieldBytes = REQUEST_BUFFER_MAX_FIELD_BYTES } = limits;
|
|
1431
1442
|
const index = requests.indexOf(request);
|
|
1432
1443
|
if (index === -1)
|
|
1433
|
-
return;
|
|
1444
|
+
return [];
|
|
1434
1445
|
synchronizeAccounting(requests, accounting);
|
|
1435
1446
|
applyFieldLimits(request, maxFieldBytes);
|
|
1436
1447
|
const previousSize = accounting.sizes[index] ?? 0;
|
|
1437
1448
|
const nextSize = estimateRequestBufferBytes(request);
|
|
1438
1449
|
accounting.sizes[index] = nextSize;
|
|
1439
1450
|
accounting.totalBytes += nextSize - previousSize;
|
|
1440
|
-
trimRequestBuffer(requests, accounting, maxEntries, maxBytes);
|
|
1451
|
+
return trimRequestBuffer(requests, accounting, maxEntries, maxBytes);
|
|
1441
1452
|
}
|
|
1442
1453
|
|
|
1443
1454
|
// ../browser-core/dist/proxyPermissions.js
|
|
@@ -3470,6 +3481,7 @@ var PAGE_ACT_ACTIONS = [
|
|
|
3470
3481
|
"page_eval"
|
|
3471
3482
|
];
|
|
3472
3483
|
var BROWSER_COMMAND_ACTIONS = {
|
|
3484
|
+
capture_checkpoint: true,
|
|
3473
3485
|
get_requests: true,
|
|
3474
3486
|
get_logs: true,
|
|
3475
3487
|
get_events: true,
|
|
@@ -3512,6 +3524,7 @@ var BROWSER_COMMAND_ACTIONS = {
|
|
|
3512
3524
|
run_actions: true
|
|
3513
3525
|
};
|
|
3514
3526
|
var EXTENSION_BROWSER_ACTIONS = {
|
|
3527
|
+
capture_checkpoint: true,
|
|
3515
3528
|
get_requests: true,
|
|
3516
3529
|
get_logs: true,
|
|
3517
3530
|
get_events: true,
|
|
@@ -3558,24 +3571,35 @@ function isExtensionBrowserAction(value) {
|
|
|
3558
3571
|
}
|
|
3559
3572
|
|
|
3560
3573
|
// ../browser-core/dist/pageAct.js
|
|
3574
|
+
var DEFAULT_PAGE_DIAGNOSTICS = {
|
|
3575
|
+
logs: true,
|
|
3576
|
+
requests: true
|
|
3577
|
+
};
|
|
3561
3578
|
function isPageActAction(action) {
|
|
3562
3579
|
return PAGE_ACT_ACTIONS.includes(action);
|
|
3563
3580
|
}
|
|
3564
3581
|
function shouldObservePageAction(action, data) {
|
|
3565
3582
|
if (!isPageActAction(action))
|
|
3566
3583
|
return false;
|
|
3584
|
+
const diagnosticsEnabled = data?.diagnostics !== void 0 && data.diagnostics !== false;
|
|
3567
3585
|
if (action === "page_eval") {
|
|
3568
|
-
return Boolean(data?.observe && typeof data.observe === "object" && !Array.isArray(data.observe));
|
|
3586
|
+
return Boolean(diagnosticsEnabled || data?.observe && typeof data.observe === "object" && !Array.isArray(data.observe));
|
|
3569
3587
|
}
|
|
3570
|
-
return data?.observe !== false;
|
|
3588
|
+
return data?.observe !== false || data?.diagnostics !== false;
|
|
3571
3589
|
}
|
|
3572
|
-
function splitObservedActionPayload(data) {
|
|
3573
|
-
const { observe, ...actionData } = data ?? {};
|
|
3590
|
+
function splitObservedActionPayload(action, data) {
|
|
3591
|
+
const { observe, diagnostics, ...actionData } = data ?? {};
|
|
3592
|
+
const setting = diagnostics;
|
|
3593
|
+
const resolvedDiagnostics = setting === false ? void 0 : setting === true ? DEFAULT_PAGE_DIAGNOSTICS : setting && typeof setting === "object" && !Array.isArray(setting) ? setting : action === "page_eval" ? void 0 : DEFAULT_PAGE_DIAGNOSTICS;
|
|
3574
3594
|
if (observe === false)
|
|
3575
|
-
return { actionData, observe: false };
|
|
3595
|
+
return { actionData, observe: false, diagnostics: resolvedDiagnostics };
|
|
3596
|
+
if (action === "page_eval" && (!observe || typeof observe !== "object")) {
|
|
3597
|
+
return { actionData, observe: false, diagnostics: resolvedDiagnostics };
|
|
3598
|
+
}
|
|
3576
3599
|
return {
|
|
3577
3600
|
actionData,
|
|
3578
|
-
observe: observe && typeof observe === "object" && !Array.isArray(observe) ? observe : {}
|
|
3601
|
+
observe: observe && typeof observe === "object" && !Array.isArray(observe) ? observe : {},
|
|
3602
|
+
diagnostics: resolvedDiagnostics
|
|
3579
3603
|
};
|
|
3580
3604
|
}
|
|
3581
3605
|
function unavailableObservation(checkpoint, error48) {
|
|
@@ -4269,6 +4293,20 @@ function assertSendRequestBase64FileLimits(byteLengths) {
|
|
|
4269
4293
|
}
|
|
4270
4294
|
}
|
|
4271
4295
|
|
|
4296
|
+
// ../browser-core/dist/sendRequestHeaders.js
|
|
4297
|
+
function resolveHeader(headers, name, fallback) {
|
|
4298
|
+
const key = findSendRequestHeaderName(headers, name);
|
|
4299
|
+
if (!key)
|
|
4300
|
+
return fallback;
|
|
4301
|
+
return headers[key] === "" ? void 0 : headers[key];
|
|
4302
|
+
}
|
|
4303
|
+
function getSendRequestSourceHeaders(targetUrl, headers = {}) {
|
|
4304
|
+
return {
|
|
4305
|
+
referer: resolveHeader(headers, "Referer", `${targetUrl.origin}/mearl`),
|
|
4306
|
+
origin: resolveHeader(headers, "Origin", targetUrl.origin)
|
|
4307
|
+
};
|
|
4308
|
+
}
|
|
4309
|
+
|
|
4272
4310
|
// ../browser-core/dist/cookie.js
|
|
4273
4311
|
function normalizeCookieDomain(input, action) {
|
|
4274
4312
|
const value = input.trim();
|
|
@@ -4423,6 +4461,83 @@ ${SOURCE_BADGES[source]}
|
|
|
4423
4461
|
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
|
4424
4462
|
}
|
|
4425
4463
|
|
|
4464
|
+
// ../browser-core/dist/capture.js
|
|
4465
|
+
var CURSOR_PREFIX = "mearl-capture-v1";
|
|
4466
|
+
function createCaptureGeneration() {
|
|
4467
|
+
return crypto.randomUUID();
|
|
4468
|
+
}
|
|
4469
|
+
function encodeCaptureCursor(cursor) {
|
|
4470
|
+
return `${CURSOR_PREFIX}:${cursor.tabId}:${cursor.generation}:${cursor.scope}:${cursor.sequence}`;
|
|
4471
|
+
}
|
|
4472
|
+
function decodeCaptureCursor(value) {
|
|
4473
|
+
const match = value.match(/^mearl-capture-v1:(\d+):([^:]+):(all|logs|requests):(\d+)$/);
|
|
4474
|
+
if (!match)
|
|
4475
|
+
throw new Error("Invalid capture cursor");
|
|
4476
|
+
const tabId = Number(match[1]);
|
|
4477
|
+
const sequence = Number(match[4]);
|
|
4478
|
+
if (!Number.isSafeInteger(tabId) || !Number.isSafeInteger(sequence)) {
|
|
4479
|
+
throw new Error("Invalid capture cursor");
|
|
4480
|
+
}
|
|
4481
|
+
return {
|
|
4482
|
+
tabId,
|
|
4483
|
+
generation: match[2],
|
|
4484
|
+
scope: match[3],
|
|
4485
|
+
sequence
|
|
4486
|
+
};
|
|
4487
|
+
}
|
|
4488
|
+
function captureCheckpoint(state) {
|
|
4489
|
+
return encodeCaptureCursor({
|
|
4490
|
+
tabId: state.tabId,
|
|
4491
|
+
generation: state.generation,
|
|
4492
|
+
sequence: state.currentSequence,
|
|
4493
|
+
scope: "all"
|
|
4494
|
+
});
|
|
4495
|
+
}
|
|
4496
|
+
function nextCaptureSequence(state) {
|
|
4497
|
+
state.currentSequence += 1;
|
|
4498
|
+
return state.currentSequence;
|
|
4499
|
+
}
|
|
4500
|
+
function resolveAfterSequence(after, state, scope) {
|
|
4501
|
+
if (!after)
|
|
4502
|
+
return 0;
|
|
4503
|
+
const cursor = decodeCaptureCursor(after);
|
|
4504
|
+
if (cursor.tabId !== state.tabId) {
|
|
4505
|
+
throw new Error(`Capture cursor belongs to tab ${cursor.tabId}, not tab ${state.tabId}`);
|
|
4506
|
+
}
|
|
4507
|
+
if (cursor.generation !== state.generation) {
|
|
4508
|
+
throw new Error("Capture cursor expired because the tab collector was restarted");
|
|
4509
|
+
}
|
|
4510
|
+
if (cursor.scope !== "all" && cursor.scope !== scope) {
|
|
4511
|
+
throw new Error(`Capture cursor is scoped to ${cursor.scope}, not ${scope}`);
|
|
4512
|
+
}
|
|
4513
|
+
if (cursor.sequence > state.currentSequence) {
|
|
4514
|
+
throw new Error("Capture cursor is ahead of the current collector state");
|
|
4515
|
+
}
|
|
4516
|
+
return cursor.sequence;
|
|
4517
|
+
}
|
|
4518
|
+
function queryCapturedEntries(buffer, state, options, matches, droppedThroughSequence = 0, scope = "all") {
|
|
4519
|
+
const { after, since, now = Date.now() } = options;
|
|
4520
|
+
const limit = Math.max(1, Math.floor(options.limit ?? 100));
|
|
4521
|
+
const afterSequence = resolveAfterSequence(after, state, scope);
|
|
4522
|
+
const sinceTimestampMs = since === void 0 ? void 0 : now - since * 1e3;
|
|
4523
|
+
const matched = buffer.filter((entry) => entry.captureSequence > afterSequence && (sinceTimestampMs === void 0 || entry.timestampMs >= sinceTimestampMs) && matches(entry));
|
|
4524
|
+
const hasMore = matched.length > limit;
|
|
4525
|
+
const entries = after ? matched.slice(0, limit) : matched.slice(-limit);
|
|
4526
|
+
const nextSequence = after && hasMore && entries.length > 0 ? entries[entries.length - 1].captureSequence : state.currentSequence;
|
|
4527
|
+
return {
|
|
4528
|
+
entries,
|
|
4529
|
+
totalMatched: matched.length,
|
|
4530
|
+
nextCursor: encodeCaptureCursor({
|
|
4531
|
+
tabId: state.tabId,
|
|
4532
|
+
generation: state.generation,
|
|
4533
|
+
sequence: nextSequence,
|
|
4534
|
+
scope
|
|
4535
|
+
}),
|
|
4536
|
+
hasMore,
|
|
4537
|
+
gap: after !== void 0 && afterSequence < droppedThroughSequence
|
|
4538
|
+
};
|
|
4539
|
+
}
|
|
4540
|
+
|
|
4426
4541
|
// src/cdp-backend/domain-manager.ts
|
|
4427
4542
|
var enabledDomains = /* @__PURE__ */ new WeakMap();
|
|
4428
4543
|
function ensureCdpDomain(client2, domain2, params = {}) {
|
|
@@ -4444,14 +4559,22 @@ function ensureCdpDomain(client2, domain2, params = {}) {
|
|
|
4444
4559
|
// src/cdp-backend/buffers.ts
|
|
4445
4560
|
var MAX_LOGS = 500;
|
|
4446
4561
|
var MAX_EVENTS = 500;
|
|
4447
|
-
|
|
4562
|
+
var COLLECTED_RESOURCE_TYPES = /* @__PURE__ */ new Set(["xhr", "fetch", "document"]);
|
|
4563
|
+
function createBuffers(tabId = 0) {
|
|
4448
4564
|
return {
|
|
4449
4565
|
requests: [],
|
|
4450
4566
|
logs: [],
|
|
4451
4567
|
events: [],
|
|
4452
4568
|
pending: /* @__PURE__ */ new Map(),
|
|
4453
4569
|
requestCounter: 0,
|
|
4454
|
-
requestBufferAccounting: createRequestBufferAccounting()
|
|
4570
|
+
requestBufferAccounting: createRequestBufferAccounting(),
|
|
4571
|
+
capture: {
|
|
4572
|
+
tabId,
|
|
4573
|
+
generation: createCaptureGeneration(),
|
|
4574
|
+
currentSequence: 0,
|
|
4575
|
+
droppedRequestsThroughSequence: 0,
|
|
4576
|
+
droppedLogsThroughSequence: 0
|
|
4577
|
+
}
|
|
4455
4578
|
};
|
|
4456
4579
|
}
|
|
4457
4580
|
function parseQueryString(url2) {
|
|
@@ -4467,12 +4590,34 @@ function parseQueryString(url2) {
|
|
|
4467
4590
|
function headersObjToArray(obj) {
|
|
4468
4591
|
return Object.entries(obj).map(([name, value]) => ({ name, value }));
|
|
4469
4592
|
}
|
|
4470
|
-
function
|
|
4593
|
+
function extractMtopApiName(url2, postData) {
|
|
4471
4594
|
try {
|
|
4472
4595
|
const u = new URL(url2);
|
|
4473
|
-
const
|
|
4474
|
-
if (
|
|
4475
|
-
|
|
4596
|
+
const pathMatch = u.pathname.match(/\/h5\/([\w.]+)\//);
|
|
4597
|
+
if (pathMatch) return pathMatch[1];
|
|
4598
|
+
const requestUrl = u.searchParams.get("requestUrl");
|
|
4599
|
+
const proxyMatch = requestUrl?.match(/\b(?:mtop|mopen)\.[\w.]+/);
|
|
4600
|
+
if (proxyMatch) return proxyMatch[0];
|
|
4601
|
+
} catch {
|
|
4602
|
+
}
|
|
4603
|
+
const urlMatch = url2.match(/\b(?:mtop|mopen)\.[\w.]+/);
|
|
4604
|
+
if (urlMatch) return urlMatch[0];
|
|
4605
|
+
if (!postData) return null;
|
|
4606
|
+
try {
|
|
4607
|
+
const parsed = JSON.parse(postData);
|
|
4608
|
+
const requestUrl = typeof parsed?.requestUrl === "string" ? parsed.requestUrl : void 0;
|
|
4609
|
+
const proxyMatch = requestUrl?.match(/\b(?:mtop|mopen)\.[\w.]+/);
|
|
4610
|
+
if (proxyMatch) return proxyMatch[0];
|
|
4611
|
+
} catch {
|
|
4612
|
+
const requestUrl = new URLSearchParams(postData).get("requestUrl");
|
|
4613
|
+
const proxyMatch = requestUrl?.match(/\b(?:mtop|mopen)\.[\w.]+/);
|
|
4614
|
+
if (proxyMatch) return proxyMatch[0];
|
|
4615
|
+
}
|
|
4616
|
+
return null;
|
|
4617
|
+
}
|
|
4618
|
+
function requestDisplayName(url2) {
|
|
4619
|
+
try {
|
|
4620
|
+
return new URL(url2).pathname;
|
|
4476
4621
|
} catch {
|
|
4477
4622
|
return url2;
|
|
4478
4623
|
}
|
|
@@ -4503,28 +4648,73 @@ function appendTrackingEvents(buffers, url2, postData, sequence) {
|
|
|
4503
4648
|
}
|
|
4504
4649
|
return true;
|
|
4505
4650
|
}
|
|
4506
|
-
function
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4651
|
+
function recordDroppedRequests(buffers, removed) {
|
|
4652
|
+
for (const request of removed) {
|
|
4653
|
+
if (request.captureSequence !== void 0) {
|
|
4654
|
+
buffers.capture.droppedRequestsThroughSequence = Math.max(
|
|
4655
|
+
buffers.capture.droppedRequestsThroughSequence,
|
|
4656
|
+
request.captureSequence
|
|
4657
|
+
);
|
|
4658
|
+
}
|
|
4659
|
+
}
|
|
4660
|
+
}
|
|
4661
|
+
function appendCapturedRequest(buffers, request) {
|
|
4662
|
+
recordDroppedRequests(
|
|
4663
|
+
buffers,
|
|
4664
|
+
appendRequestToBuffer(buffers.requests, buffers.requestBufferAccounting, request)
|
|
4665
|
+
);
|
|
4666
|
+
}
|
|
4667
|
+
function refreshCapturedRequest(buffers, request) {
|
|
4668
|
+
recordDroppedRequests(
|
|
4669
|
+
buffers,
|
|
4670
|
+
refreshRequestInBuffer(buffers.requests, buffers.requestBufferAccounting, request)
|
|
4671
|
+
);
|
|
4672
|
+
}
|
|
4673
|
+
function appendCapturedLog(buffers, log2) {
|
|
4674
|
+
buffers.logs.push({ ...log2, captureSequence: nextCaptureSequence(buffers.capture) });
|
|
4675
|
+
if (buffers.logs.length > MAX_LOGS) {
|
|
4676
|
+
const removed = buffers.logs.shift();
|
|
4677
|
+
if (removed) buffers.capture.droppedLogsThroughSequence = removed.captureSequence;
|
|
4678
|
+
}
|
|
4679
|
+
}
|
|
4680
|
+
async function setupBufferListeners(client2, buffers) {
|
|
4516
4681
|
client2.on("Network.requestWillBeSent", (params) => {
|
|
4517
4682
|
const url2 = params.request?.url ?? "";
|
|
4518
|
-
|
|
4683
|
+
if (!url2.startsWith("http")) return;
|
|
4684
|
+
if (isTrackingUrl(url2)) {
|
|
4685
|
+
const sequence = ++buffers.requestCounter;
|
|
4686
|
+
const captured = appendTrackingEvents(buffers, url2, params.request?.postData, sequence);
|
|
4687
|
+
if (!captured && params.request?.hasPostData && !params.request?.postData) {
|
|
4688
|
+
client2.sendCommand("Network.getRequestPostData", { requestId: params.requestId }, 1e4).then((result) => appendTrackingEvents(buffers, url2, result?.postData, sequence)).catch(() => {
|
|
4689
|
+
});
|
|
4690
|
+
}
|
|
4691
|
+
return;
|
|
4692
|
+
}
|
|
4693
|
+
const resourceType = String(params.type ?? "").toLowerCase();
|
|
4694
|
+
const mtopApiName = extractMtopApiName(url2, params.request?.postData);
|
|
4695
|
+
const isMtop = mtopApiName !== null;
|
|
4696
|
+
if (!isMtop && !COLLECTED_RESOURCE_TYPES.has(resourceType)) return;
|
|
4697
|
+
const ts = params.timestamp;
|
|
4698
|
+
const timestampMs2 = params.wallTime !== void 0 ? Math.floor(params.wallTime * 1e3) : Date.now();
|
|
4699
|
+
const redirected = buffers.pending.get(params.requestId);
|
|
4700
|
+
if (redirected && params.redirectResponse) {
|
|
4701
|
+
redirected.status = params.redirectResponse.status ?? 0;
|
|
4702
|
+
redirected.statusText = params.redirectResponse.statusText ?? "";
|
|
4703
|
+
redirected.duration = ts !== void 0 && redirected.startTs !== void 0 ? Math.round((ts - redirected.startTs) * 1e3) : void 0;
|
|
4704
|
+
redirected.isPending = false;
|
|
4705
|
+
refreshCapturedRequest(buffers, redirected);
|
|
4706
|
+
buffers.pending.delete(params.requestId);
|
|
4707
|
+
}
|
|
4519
4708
|
const id = ++buffers.requestCounter;
|
|
4709
|
+
const captureSequence = nextCaptureSequence(buffers.capture);
|
|
4520
4710
|
const partial2 = {
|
|
4521
4711
|
id,
|
|
4522
4712
|
requestId: params.requestId,
|
|
4523
|
-
timestamp: new Date(
|
|
4524
|
-
timestampMs:
|
|
4713
|
+
timestamp: new Date(timestampMs2).toISOString(),
|
|
4714
|
+
timestampMs: timestampMs2,
|
|
4525
4715
|
method: params.request?.method ?? "GET",
|
|
4526
4716
|
url: url2,
|
|
4527
|
-
apiName:
|
|
4717
|
+
apiName: mtopApiName ?? requestDisplayName(url2),
|
|
4528
4718
|
headers: headersObjToArray(params.request?.headers ?? {}),
|
|
4529
4719
|
postData: parsePostData(params.request?.postData),
|
|
4530
4720
|
queryString: parseQueryString(url2),
|
|
@@ -4535,16 +4725,14 @@ function setupBufferListeners(client2, buffers) {
|
|
|
4535
4725
|
isProxy: false,
|
|
4536
4726
|
proxyRequestUrl: null,
|
|
4537
4727
|
proxyData: null,
|
|
4538
|
-
startTs: ts
|
|
4728
|
+
startTs: ts,
|
|
4729
|
+
captureSequence,
|
|
4730
|
+
isPending: true,
|
|
4731
|
+
source: isMtop ? "mtop" : "requests",
|
|
4732
|
+
resourceType
|
|
4539
4733
|
};
|
|
4540
4734
|
buffers.pending.set(params.requestId, partial2);
|
|
4541
|
-
|
|
4542
|
-
if (!captured && params.request?.hasPostData && !params.request?.postData) {
|
|
4543
|
-
client2.sendCommand("Network.getRequestPostData", { requestId: params.requestId }, 1e4).then((result) => {
|
|
4544
|
-
appendTrackingEvents(buffers, url2, result?.postData, id);
|
|
4545
|
-
}).catch(() => {
|
|
4546
|
-
});
|
|
4547
|
-
}
|
|
4735
|
+
appendCapturedRequest(buffers, partial2);
|
|
4548
4736
|
});
|
|
4549
4737
|
client2.on("Network.responseReceived", (params) => {
|
|
4550
4738
|
const partial2 = buffers.pending.get(params.requestId);
|
|
@@ -4552,73 +4740,110 @@ function setupBufferListeners(client2, buffers) {
|
|
|
4552
4740
|
partial2.status = params.response?.status ?? 0;
|
|
4553
4741
|
partial2.statusText = params.response?.statusText ?? "";
|
|
4554
4742
|
partial2.responseHeaders = headersObjToArray(params.response?.headers ?? {});
|
|
4743
|
+
refreshCapturedRequest(buffers, partial2);
|
|
4555
4744
|
});
|
|
4556
4745
|
client2.on("Network.loadingFinished", (params) => {
|
|
4557
4746
|
const partial2 = buffers.pending.get(params.requestId);
|
|
4558
4747
|
if (!partial2) return;
|
|
4559
4748
|
buffers.pending.delete(params.requestId);
|
|
4560
|
-
const endTs = params.timestamp
|
|
4561
|
-
const duration3 = Math.round((endTs - partial2.startTs) * 1e3);
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
isPending: false
|
|
4566
|
-
};
|
|
4749
|
+
const endTs = params.timestamp;
|
|
4750
|
+
const duration3 = endTs !== void 0 && partial2.startTs !== void 0 ? Math.round((endTs - partial2.startTs) * 1e3) : void 0;
|
|
4751
|
+
partial2.duration = duration3;
|
|
4752
|
+
partial2.isPending = false;
|
|
4753
|
+
refreshCapturedRequest(buffers, partial2);
|
|
4567
4754
|
client2.sendCommand("Network.getResponseBody", { requestId: params.requestId }, 1e4).then((result) => {
|
|
4568
|
-
|
|
4569
|
-
if (typeof
|
|
4755
|
+
partial2.responseBody = result.base64Encoded ? Buffer.from(result.body, "base64").toString("utf-8") : result.body;
|
|
4756
|
+
if (typeof partial2.responseBody === "string") {
|
|
4570
4757
|
try {
|
|
4571
|
-
|
|
4758
|
+
partial2.responseBody = JSON.parse(partial2.responseBody);
|
|
4572
4759
|
} catch {
|
|
4573
4760
|
}
|
|
4574
4761
|
}
|
|
4575
|
-
|
|
4762
|
+
refreshCapturedRequest(buffers, partial2);
|
|
4576
4763
|
}).catch(() => {
|
|
4577
4764
|
});
|
|
4578
|
-
appendRequestToBuffer(buffers.requests, buffers.requestBufferAccounting, req);
|
|
4579
4765
|
});
|
|
4580
4766
|
client2.on("Network.loadingFailed", (params) => {
|
|
4581
4767
|
const partial2 = buffers.pending.get(params.requestId);
|
|
4582
4768
|
if (!partial2) return;
|
|
4583
4769
|
buffers.pending.delete(params.requestId);
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
isPending: false
|
|
4590
|
-
};
|
|
4591
|
-
appendRequestToBuffer(buffers.requests, buffers.requestBufferAccounting, req);
|
|
4770
|
+
partial2.status = 0;
|
|
4771
|
+
partial2.statusText = params.errorText ?? "Failed";
|
|
4772
|
+
partial2.duration = params.timestamp !== void 0 && partial2.startTs !== void 0 ? Math.round((params.timestamp - partial2.startTs) * 1e3) : void 0;
|
|
4773
|
+
partial2.isPending = false;
|
|
4774
|
+
refreshCapturedRequest(buffers, partial2);
|
|
4592
4775
|
});
|
|
4593
4776
|
client2.on("Runtime.consoleAPICalled", (params) => {
|
|
4594
|
-
const
|
|
4777
|
+
const levelMap = {
|
|
4778
|
+
warning: "warn",
|
|
4779
|
+
debug: "debug",
|
|
4780
|
+
info: "info",
|
|
4781
|
+
error: "error",
|
|
4782
|
+
assert: "error"
|
|
4783
|
+
};
|
|
4784
|
+
const level = levelMap[params.type] ?? "log";
|
|
4595
4785
|
const args = (params.args ?? []).map((arg) => {
|
|
4596
4786
|
if (arg.type === "string") return arg.value;
|
|
4597
4787
|
if (arg.value !== void 0) return String(arg.value);
|
|
4598
4788
|
if (arg.description !== void 0) return arg.description;
|
|
4599
4789
|
return JSON.stringify(arg);
|
|
4600
4790
|
});
|
|
4601
|
-
|
|
4791
|
+
appendCapturedLog(buffers, {
|
|
4602
4792
|
level,
|
|
4603
4793
|
message: args.join(" "),
|
|
4604
|
-
|
|
4605
|
-
source: "console",
|
|
4606
|
-
args
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4794
|
+
timestampMs: params.timestamp ?? Date.now(),
|
|
4795
|
+
source: params.stackTrace?.callFrames?.[0]?.url ? `${params.stackTrace.callFrames[0].url.split("/").pop() || params.stackTrace.callFrames[0].url}:${params.stackTrace.callFrames[0].lineNumber + 1}` : "console",
|
|
4796
|
+
args,
|
|
4797
|
+
origin: "console"
|
|
4798
|
+
});
|
|
4799
|
+
});
|
|
4800
|
+
client2.on("Runtime.exceptionThrown", (params) => {
|
|
4801
|
+
const details = params.exceptionDetails ?? {};
|
|
4802
|
+
const exception = details.exception;
|
|
4803
|
+
const message = exception?.description ?? (exception?.value !== void 0 ? String(exception.value) : void 0) ?? details.text ?? "Uncaught exception";
|
|
4804
|
+
const topFrame = details.stackTrace?.callFrames?.[0];
|
|
4805
|
+
const url2 = topFrame?.url || details.url;
|
|
4806
|
+
const lineNumber = topFrame?.lineNumber ?? details.lineNumber;
|
|
4807
|
+
const source = url2 ? `${url2.split("/").pop() || url2}${lineNumber !== void 0 ? `:${lineNumber + 1}` : ""}` : void 0;
|
|
4808
|
+
appendCapturedLog(buffers, {
|
|
4809
|
+
level: "error",
|
|
4810
|
+
message,
|
|
4811
|
+
timestampMs: params.timestamp ?? Date.now(),
|
|
4812
|
+
...source ? { source } : {},
|
|
4813
|
+
args: [message],
|
|
4814
|
+
origin: "exception"
|
|
4815
|
+
});
|
|
4610
4816
|
});
|
|
4611
4817
|
client2.on("Log.entryAdded", (params) => {
|
|
4612
|
-
const entry = {
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4818
|
+
const entry = params.entry ?? {};
|
|
4819
|
+
const levelMap = {
|
|
4820
|
+
verbose: "log",
|
|
4821
|
+
info: "info",
|
|
4822
|
+
warning: "warn",
|
|
4823
|
+
error: "error"
|
|
4618
4824
|
};
|
|
4619
|
-
|
|
4620
|
-
|
|
4825
|
+
const args = (entry.args ?? []).map((arg) => {
|
|
4826
|
+
if (arg.value !== void 0) return String(arg.value);
|
|
4827
|
+
return arg.description ?? `[${arg.type || "Object"}]`;
|
|
4828
|
+
});
|
|
4829
|
+
const message = entry.text || args.join(" ");
|
|
4830
|
+
appendCapturedLog(buffers, {
|
|
4831
|
+
level: levelMap[entry.level] ?? entry.level ?? "log",
|
|
4832
|
+
message,
|
|
4833
|
+
timestampMs: entry.timestamp ?? Date.now(),
|
|
4834
|
+
source: entry.url ? `${entry.url.split("/").pop() || entry.url}${entry.lineNumber !== void 0 ? `:${entry.lineNumber + 1}` : ""}` : entry.source ?? "other",
|
|
4835
|
+
args: args.length > 0 ? args : [message],
|
|
4836
|
+
origin: "browser"
|
|
4837
|
+
});
|
|
4621
4838
|
});
|
|
4839
|
+
await Promise.all([
|
|
4840
|
+
ensureCdpDomain(client2, "Network", {
|
|
4841
|
+
maxTotalBufferSize: 10 * 1024 * 1024,
|
|
4842
|
+
maxPostDataSize: 5 * 1024 * 1024
|
|
4843
|
+
}),
|
|
4844
|
+
ensureCdpDomain(client2, "Runtime"),
|
|
4845
|
+
ensureCdpDomain(client2, "Log")
|
|
4846
|
+
]);
|
|
4622
4847
|
}
|
|
4623
4848
|
|
|
4624
4849
|
// src/cdp-backend/discover.ts
|
|
@@ -4777,9 +5002,21 @@ var CdpSession = class {
|
|
|
4777
5002
|
} catch {
|
|
4778
5003
|
client2 = await CdpClient.connect(target.webSocketDebuggerUrl);
|
|
4779
5004
|
}
|
|
4780
|
-
|
|
4781
|
-
|
|
5005
|
+
let tabId;
|
|
5006
|
+
for (const [virtualId, registeredTargetId] of this.tabIdMap) {
|
|
5007
|
+
if (registeredTargetId === target.id) {
|
|
5008
|
+
tabId = virtualId;
|
|
5009
|
+
break;
|
|
5010
|
+
}
|
|
5011
|
+
}
|
|
5012
|
+
if (tabId === void 0) {
|
|
5013
|
+
tabId = this.nextTabId++;
|
|
5014
|
+
this.tabIdMap.set(tabId, target.id);
|
|
5015
|
+
}
|
|
5016
|
+
const buffers = createBuffers(tabId);
|
|
5017
|
+
await setupBufferListeners(client2, buffers);
|
|
4782
5018
|
const session = {
|
|
5019
|
+
tabId,
|
|
4783
5020
|
client: client2,
|
|
4784
5021
|
buffers,
|
|
4785
5022
|
targetId: target.id,
|
|
@@ -6035,6 +6272,143 @@ async function enrichCdpPageChangeSetWithRefs(session, observation) {
|
|
|
6035
6272
|
);
|
|
6036
6273
|
}
|
|
6037
6274
|
|
|
6275
|
+
// src/cdp-backend/request-handlers.ts
|
|
6276
|
+
function filterRequests(buffers, opts) {
|
|
6277
|
+
const pattern = opts.filter ? compileTextPattern(opts.filter) : void 0;
|
|
6278
|
+
return queryCapturedEntries(
|
|
6279
|
+
buffers.requests.filter(
|
|
6280
|
+
(request) => Number.isSafeInteger(request.captureSequence)
|
|
6281
|
+
),
|
|
6282
|
+
buffers.capture,
|
|
6283
|
+
{ after: opts.after, since: opts.since, limit: opts.count ?? 10 },
|
|
6284
|
+
(request) => (!opts.source || opts.source === "all" || request.source === opts.source) && (!pattern || matchesTextPattern(request.url, pattern) || matchesTextPattern(request.apiName, pattern)),
|
|
6285
|
+
buffers.capture.droppedRequestsThroughSequence,
|
|
6286
|
+
"requests"
|
|
6287
|
+
);
|
|
6288
|
+
}
|
|
6289
|
+
async function cdpGetRequests(session, data) {
|
|
6290
|
+
const opts = {
|
|
6291
|
+
count: data.count ?? 10,
|
|
6292
|
+
filter: data.filter,
|
|
6293
|
+
since: data.since,
|
|
6294
|
+
after: data.after,
|
|
6295
|
+
source: data.source,
|
|
6296
|
+
applyHiddenFilter: data.applyHiddenFilter !== false
|
|
6297
|
+
};
|
|
6298
|
+
const captured = filterRequests(session.buffers, opts);
|
|
6299
|
+
const serializeOpts = {
|
|
6300
|
+
includeBody: data.includeBody !== false,
|
|
6301
|
+
includeHeaders: data.includeHeaders === true,
|
|
6302
|
+
maxBodySize: data.maxBodySize ?? 5e4,
|
|
6303
|
+
fields: data.fields,
|
|
6304
|
+
keysOnly: data.keysOnly === true
|
|
6305
|
+
};
|
|
6306
|
+
return {
|
|
6307
|
+
meta: {
|
|
6308
|
+
count: captured.entries.length,
|
|
6309
|
+
totalMatched: captured.totalMatched,
|
|
6310
|
+
totalInBuffer: session.buffers.requests.length,
|
|
6311
|
+
filter: data.filter,
|
|
6312
|
+
since: data.since,
|
|
6313
|
+
after: data.after,
|
|
6314
|
+
nextCursor: captured.nextCursor,
|
|
6315
|
+
hasMore: captured.hasMore,
|
|
6316
|
+
gap: captured.gap,
|
|
6317
|
+
source: "cdp"
|
|
6318
|
+
},
|
|
6319
|
+
requests: captured.entries.map((r) => serializeRequest(r, serializeOpts))
|
|
6320
|
+
};
|
|
6321
|
+
}
|
|
6322
|
+
async function cdpGetLogs(session, data) {
|
|
6323
|
+
const { level, since, after, limit = 100, filter } = data;
|
|
6324
|
+
const pattern = filter ? compileTextPattern(filter) : void 0;
|
|
6325
|
+
const captured = queryCapturedEntries(
|
|
6326
|
+
session.buffers.logs,
|
|
6327
|
+
session.buffers.capture,
|
|
6328
|
+
{ after, since, limit },
|
|
6329
|
+
(log2) => (!level || level === "all" || log2.level === level) && (!pattern || matchesTextPattern(log2.message, pattern) || log2.args.some((arg) => matchesTextPattern(arg, pattern))),
|
|
6330
|
+
session.buffers.capture.droppedLogsThroughSequence,
|
|
6331
|
+
"logs"
|
|
6332
|
+
);
|
|
6333
|
+
const captureStatus = session.buffers.logs.length === 0 ? "armed" : "active";
|
|
6334
|
+
return {
|
|
6335
|
+
meta: {
|
|
6336
|
+
count: captured.entries.length,
|
|
6337
|
+
totalMatched: captured.totalMatched,
|
|
6338
|
+
totalInBuffer: session.buffers.logs.length,
|
|
6339
|
+
level: level || "all",
|
|
6340
|
+
since,
|
|
6341
|
+
after,
|
|
6342
|
+
filter,
|
|
6343
|
+
nextCursor: captured.nextCursor,
|
|
6344
|
+
hasMore: captured.hasMore,
|
|
6345
|
+
gap: captured.gap,
|
|
6346
|
+
captureStatus,
|
|
6347
|
+
...captureStatus === "armed" && {
|
|
6348
|
+
hint: "Log capture is active, but this tab has no captured history yet. Reload the current tab or repeat the triggering action, then call get_logs again."
|
|
6349
|
+
},
|
|
6350
|
+
source: "cdp"
|
|
6351
|
+
},
|
|
6352
|
+
logs: captured.entries
|
|
6353
|
+
};
|
|
6354
|
+
}
|
|
6355
|
+
async function cdpCaptureCheckpoint(session, _data) {
|
|
6356
|
+
return {
|
|
6357
|
+
tabId: session.tabId,
|
|
6358
|
+
cursor: captureCheckpoint(session.buffers.capture),
|
|
6359
|
+
timestampMs: Date.now(),
|
|
6360
|
+
captureStatus: session.buffers.capture.currentSequence === 0 ? "armed" : "active"
|
|
6361
|
+
};
|
|
6362
|
+
}
|
|
6363
|
+
async function collectCdpPageDiagnostics(session, after, diagnostics) {
|
|
6364
|
+
const result = {};
|
|
6365
|
+
if (diagnostics.logs) {
|
|
6366
|
+
const options = diagnostics.logs === true ? { level: "error", limit: 100 } : { level: "error", limit: 100, ...diagnostics.logs };
|
|
6367
|
+
result.logs = await cdpGetLogs(session, { ...options, after });
|
|
6368
|
+
}
|
|
6369
|
+
if (diagnostics.requests) {
|
|
6370
|
+
const options = diagnostics.requests === true ? { source: "all", includeBody: false, count: 100 } : {
|
|
6371
|
+
source: "all",
|
|
6372
|
+
includeBody: false,
|
|
6373
|
+
count: 100,
|
|
6374
|
+
...diagnostics.requests
|
|
6375
|
+
};
|
|
6376
|
+
result.requests = await cdpGetRequests(session, { ...options, after });
|
|
6377
|
+
}
|
|
6378
|
+
return result;
|
|
6379
|
+
}
|
|
6380
|
+
async function cdpGetEvents(session, data) {
|
|
6381
|
+
const { source = "all", event_type, since, limit = 20, filter, includeRaw = false } = data;
|
|
6382
|
+
const response = queryTrackingEvents(session.buffers.events, {
|
|
6383
|
+
source,
|
|
6384
|
+
event_type,
|
|
6385
|
+
since,
|
|
6386
|
+
limit,
|
|
6387
|
+
filter
|
|
6388
|
+
});
|
|
6389
|
+
const captureStatus = response.totalInBuffer === 0 ? "armed" : "active";
|
|
6390
|
+
const hint = response.events.length === 0 && captureStatus === "armed" ? TRACKING_CAPTURE_ARMED_HINT : void 0;
|
|
6391
|
+
return {
|
|
6392
|
+
meta: {
|
|
6393
|
+
count: response.events.length,
|
|
6394
|
+
totalMatched: response.totalMatched,
|
|
6395
|
+
totalInBuffer: response.totalInBuffer,
|
|
6396
|
+
source,
|
|
6397
|
+
captureStatus,
|
|
6398
|
+
captureSource: "cdp",
|
|
6399
|
+
includeRaw,
|
|
6400
|
+
hint
|
|
6401
|
+
},
|
|
6402
|
+
events: response.events.map((event) => formatTrackingEvent(event, includeRaw))
|
|
6403
|
+
};
|
|
6404
|
+
}
|
|
6405
|
+
registerActions([
|
|
6406
|
+
{ name: "capture_checkpoint", session: "page", handler: cdpCaptureCheckpoint },
|
|
6407
|
+
{ name: "get_requests", session: "page", handler: cdpGetRequests },
|
|
6408
|
+
{ name: "get_logs", session: "page", handler: cdpGetLogs },
|
|
6409
|
+
{ name: "get_events", session: "page", handler: cdpGetEvents }
|
|
6410
|
+
]);
|
|
6411
|
+
|
|
6038
6412
|
// src/cdp-backend/composite-handlers.ts
|
|
6039
6413
|
async function cdpRunActions(session, data, controlSource = "local") {
|
|
6040
6414
|
const { actions, tabId } = data;
|
|
@@ -6110,21 +6484,42 @@ async function cdpRunActions(session, data, controlSource = "local") {
|
|
|
6110
6484
|
};
|
|
6111
6485
|
}
|
|
6112
6486
|
async function cdpObservedPageAction(session, action, data, controlSource = "local") {
|
|
6113
|
-
const { actionData, observe } = splitObservedActionPayload(data);
|
|
6114
|
-
if (observe === false) {
|
|
6115
|
-
return dispatchCdpAction(session, action, actionData, controlSource);
|
|
6116
|
-
}
|
|
6487
|
+
const { actionData, observe, diagnostics } = splitObservedActionPayload(action, data);
|
|
6117
6488
|
const { tabId } = actionData;
|
|
6118
6489
|
if (typeof tabId !== "number") throw new Error(`${action} requires a numeric tabId`);
|
|
6119
6490
|
const pageSession = await session.getPageSession(tabId);
|
|
6120
6491
|
await ensureControlledIndicator(pageSession, controlSource);
|
|
6121
|
-
|
|
6492
|
+
if (observe === false) {
|
|
6493
|
+
if (!diagnostics) return dispatchCdpAction(session, action, actionData, controlSource);
|
|
6494
|
+
const cursor = captureCheckpoint(pageSession.buffers.capture);
|
|
6495
|
+
let actionResult;
|
|
6496
|
+
let actionError;
|
|
6497
|
+
try {
|
|
6498
|
+
actionResult = await dispatchCdpAction(session, action, actionData, controlSource);
|
|
6499
|
+
} catch (error48) {
|
|
6500
|
+
actionError = error48 instanceof Error ? error48.message : String(error48);
|
|
6501
|
+
}
|
|
6502
|
+
return {
|
|
6503
|
+
action: {
|
|
6504
|
+
name: action,
|
|
6505
|
+
success: actionError === void 0,
|
|
6506
|
+
...actionResult !== void 0 ? { data: actionResult } : {},
|
|
6507
|
+
...actionError ? { error: actionError } : {}
|
|
6508
|
+
},
|
|
6509
|
+
diagnostics: await collectCdpPageDiagnostics(pageSession, cursor, diagnostics)
|
|
6510
|
+
};
|
|
6511
|
+
}
|
|
6512
|
+
let diagnosticsCursor;
|
|
6513
|
+
const result = await runPageAct(
|
|
6122
6514
|
{ action, actionData, observe },
|
|
6123
6515
|
{
|
|
6124
6516
|
startObservation: () => startPageObservation(pageSession),
|
|
6125
6517
|
finishObservation: (checkpoint, options) => finishPageObservation(pageSession, checkpoint, options),
|
|
6126
6518
|
startNavigationObserver: (options) => startCdpNavigationObserver(session, pageSession, options.urlBefore, options),
|
|
6127
|
-
executeAction: (name, params) =>
|
|
6519
|
+
executeAction: (name, params) => {
|
|
6520
|
+
if (diagnostics) diagnosticsCursor = captureCheckpoint(pageSession.buffers.capture);
|
|
6521
|
+
return dispatchCdpAction(session, name, { ...params, tabId }, controlSource);
|
|
6522
|
+
},
|
|
6128
6523
|
finalizeObservation: (observation) => {
|
|
6129
6524
|
if (observation.mode === "delta") {
|
|
6130
6525
|
return enrichCdpPageChangeSetWithRefs(pageSession, observation);
|
|
@@ -6134,6 +6529,11 @@ async function cdpObservedPageAction(session, action, data, controlSource = "loc
|
|
|
6134
6529
|
disposeObservation: () => disposePageObservation(pageSession)
|
|
6135
6530
|
}
|
|
6136
6531
|
);
|
|
6532
|
+
if (!diagnostics || !diagnosticsCursor) return result;
|
|
6533
|
+
return {
|
|
6534
|
+
...result,
|
|
6535
|
+
diagnostics: await collectCdpPageDiagnostics(pageSession, diagnosticsCursor, diagnostics)
|
|
6536
|
+
};
|
|
6137
6537
|
}
|
|
6138
6538
|
registerActions([{ name: "run_actions", session: "browser", handler: cdpRunActions }]);
|
|
6139
6539
|
|
|
@@ -6721,112 +7121,6 @@ function listCloudConnectors() {
|
|
|
6721
7121
|
return { connectors: pushIfChanged() };
|
|
6722
7122
|
}
|
|
6723
7123
|
|
|
6724
|
-
// src/cdp-backend/request-handlers.ts
|
|
6725
|
-
function filterRequests(buffers, opts) {
|
|
6726
|
-
let requests = [...buffers.requests];
|
|
6727
|
-
if (opts.since !== void 0) {
|
|
6728
|
-
requests = requests.filter((r) => r.timestampMs >= opts.since);
|
|
6729
|
-
}
|
|
6730
|
-
if (opts.filter) {
|
|
6731
|
-
const pattern = compileTextPattern(opts.filter);
|
|
6732
|
-
requests = requests.filter(
|
|
6733
|
-
(r) => matchesTextPattern(r.url, pattern) || matchesTextPattern(r.apiName, pattern)
|
|
6734
|
-
);
|
|
6735
|
-
}
|
|
6736
|
-
if (opts.source === "mtop") {
|
|
6737
|
-
requests = requests.filter((r) => r.url?.includes("/h5/") || r.url?.includes("mtop"));
|
|
6738
|
-
}
|
|
6739
|
-
const count = opts.count ?? 10;
|
|
6740
|
-
return {
|
|
6741
|
-
requests: requests.slice(-count),
|
|
6742
|
-
totalMatched: requests.length
|
|
6743
|
-
};
|
|
6744
|
-
}
|
|
6745
|
-
async function cdpGetRequests(session, data) {
|
|
6746
|
-
const opts = {
|
|
6747
|
-
count: data.count ?? 10,
|
|
6748
|
-
filter: data.filter,
|
|
6749
|
-
since: data.since,
|
|
6750
|
-
source: data.source,
|
|
6751
|
-
applyHiddenFilter: data.applyHiddenFilter !== false
|
|
6752
|
-
};
|
|
6753
|
-
const { requests, totalMatched } = filterRequests(session.buffers, opts);
|
|
6754
|
-
const serializeOpts = {
|
|
6755
|
-
includeBody: data.includeBody !== false,
|
|
6756
|
-
includeHeaders: data.includeHeaders === true,
|
|
6757
|
-
maxBodySize: data.maxBodySize ?? 5e4,
|
|
6758
|
-
fields: data.fields,
|
|
6759
|
-
keysOnly: data.keysOnly === true
|
|
6760
|
-
};
|
|
6761
|
-
return {
|
|
6762
|
-
meta: {
|
|
6763
|
-
count: requests.length,
|
|
6764
|
-
totalMatched,
|
|
6765
|
-
totalInBuffer: session.buffers.requests.length,
|
|
6766
|
-
filter: data.filter,
|
|
6767
|
-
since: data.since,
|
|
6768
|
-
source: "cdp"
|
|
6769
|
-
},
|
|
6770
|
-
requests: requests.map((r) => serializeRequest(r, serializeOpts))
|
|
6771
|
-
};
|
|
6772
|
-
}
|
|
6773
|
-
async function cdpGetLogs(session, data) {
|
|
6774
|
-
const { level, since, limit = 100, filter } = data;
|
|
6775
|
-
let logs = [...session.buffers.logs];
|
|
6776
|
-
if (since !== void 0) {
|
|
6777
|
-
logs = logs.filter((l) => l.timestamp >= since);
|
|
6778
|
-
}
|
|
6779
|
-
if (level && level !== "all") {
|
|
6780
|
-
logs = logs.filter((l) => l.level === level);
|
|
6781
|
-
}
|
|
6782
|
-
if (filter) {
|
|
6783
|
-
const f = filter.toLowerCase();
|
|
6784
|
-
logs = logs.filter((l) => l.message?.toLowerCase().includes(f));
|
|
6785
|
-
}
|
|
6786
|
-
logs = logs.slice(-limit);
|
|
6787
|
-
return {
|
|
6788
|
-
meta: {
|
|
6789
|
-
count: logs.length,
|
|
6790
|
-
totalMatched: logs.length,
|
|
6791
|
-
level: level || "all",
|
|
6792
|
-
since,
|
|
6793
|
-
filter,
|
|
6794
|
-
source: "cdp"
|
|
6795
|
-
},
|
|
6796
|
-
logs
|
|
6797
|
-
};
|
|
6798
|
-
}
|
|
6799
|
-
async function cdpGetEvents(session, data) {
|
|
6800
|
-
const { source = "all", event_type, since, limit = 20, filter, includeRaw = false } = data;
|
|
6801
|
-
const response = queryTrackingEvents(session.buffers.events, {
|
|
6802
|
-
source,
|
|
6803
|
-
event_type,
|
|
6804
|
-
since,
|
|
6805
|
-
limit,
|
|
6806
|
-
filter
|
|
6807
|
-
});
|
|
6808
|
-
const captureStatus = response.totalInBuffer === 0 ? "armed" : "active";
|
|
6809
|
-
const hint = response.events.length === 0 && captureStatus === "armed" ? TRACKING_CAPTURE_ARMED_HINT : void 0;
|
|
6810
|
-
return {
|
|
6811
|
-
meta: {
|
|
6812
|
-
count: response.events.length,
|
|
6813
|
-
totalMatched: response.totalMatched,
|
|
6814
|
-
totalInBuffer: response.totalInBuffer,
|
|
6815
|
-
source,
|
|
6816
|
-
captureStatus,
|
|
6817
|
-
captureSource: "cdp",
|
|
6818
|
-
includeRaw,
|
|
6819
|
-
hint
|
|
6820
|
-
},
|
|
6821
|
-
events: response.events.map((event) => formatTrackingEvent(event, includeRaw))
|
|
6822
|
-
};
|
|
6823
|
-
}
|
|
6824
|
-
registerActions([
|
|
6825
|
-
{ name: "get_requests", session: "page", handler: cdpGetRequests },
|
|
6826
|
-
{ name: "get_logs", session: "page", handler: cdpGetLogs },
|
|
6827
|
-
{ name: "get_events", session: "page", handler: cdpGetEvents }
|
|
6828
|
-
]);
|
|
6829
|
-
|
|
6830
7124
|
// src/cdp-backend/send-request.ts
|
|
6831
7125
|
import { readFile } from "node:fs/promises";
|
|
6832
7126
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -6836,6 +7130,10 @@ function setHeader(headers, name, value) {
|
|
|
6836
7130
|
if (existing && existing !== name) delete headers[existing];
|
|
6837
7131
|
headers[name] = value;
|
|
6838
7132
|
}
|
|
7133
|
+
function removeHeader(headers, name) {
|
|
7134
|
+
const existing = findSendRequestHeaderName(headers, name);
|
|
7135
|
+
if (existing) delete headers[existing];
|
|
7136
|
+
}
|
|
6839
7137
|
function escapeMultipartQuotedValue(value) {
|
|
6840
7138
|
return value.replace(/\\/g, "\\\\").replace(/"/g, "%22");
|
|
6841
7139
|
}
|
|
@@ -6944,10 +7242,19 @@ async function executeNodeSendRequest(data, cookieMap = /* @__PURE__ */ new Map(
|
|
|
6944
7242
|
Accept: "application/json, text/plain, */*",
|
|
6945
7243
|
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
|
|
6946
7244
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
|
|
6947
|
-
Referer: targetUrl.origin + "/mearl",
|
|
6948
|
-
Origin: targetUrl.origin,
|
|
6949
7245
|
...headers
|
|
6950
7246
|
};
|
|
7247
|
+
const resolvedSourceHeaders = getSendRequestSourceHeaders(targetUrl, headers);
|
|
7248
|
+
if (resolvedSourceHeaders.referer) {
|
|
7249
|
+
setHeader(requestHeaders, "Referer", resolvedSourceHeaders.referer);
|
|
7250
|
+
} else {
|
|
7251
|
+
removeHeader(requestHeaders, "Referer");
|
|
7252
|
+
}
|
|
7253
|
+
if (resolvedSourceHeaders.origin) {
|
|
7254
|
+
setHeader(requestHeaders, "Origin", resolvedSourceHeaders.origin);
|
|
7255
|
+
} else {
|
|
7256
|
+
removeHeader(requestHeaders, "Origin");
|
|
7257
|
+
}
|
|
6951
7258
|
const cookieHeader = [...cookieMap.entries()].map(([key, value]) => `${key}=${value}`).join("; ");
|
|
6952
7259
|
if (cookieHeader) setHeader(requestHeaders, "Cookie", cookieHeader);
|
|
6953
7260
|
const xsrfToken = cookieMap.get("XSRF-TOKEN");
|
|
@@ -7574,6 +7881,14 @@ async function cdpTdbankAccount(cdpSession2, data) {
|
|
|
7574
7881
|
registerActions([{ name: "tdbank_account", session: "browser", handler: cdpTdbankAccount }]);
|
|
7575
7882
|
|
|
7576
7883
|
// src/cdp-backend/tab-handlers.ts
|
|
7884
|
+
function currentCapture(pageSession) {
|
|
7885
|
+
return {
|
|
7886
|
+
tabId: pageSession.tabId,
|
|
7887
|
+
cursor: captureCheckpoint(pageSession.buffers.capture),
|
|
7888
|
+
timestampMs: Date.now(),
|
|
7889
|
+
captureStatus: pageSession.buffers.capture.currentSequence === 0 ? "armed" : "active"
|
|
7890
|
+
};
|
|
7891
|
+
}
|
|
7577
7892
|
async function cdpTabOpen(session, data, controlSource = "local") {
|
|
7578
7893
|
const { url: url2, active = false, emulation, reuse = "never", match } = data;
|
|
7579
7894
|
if (!url2 || typeof url2 !== "string") {
|
|
@@ -7600,12 +7915,14 @@ async function cdpTabOpen(session, data, controlSource = "local") {
|
|
|
7600
7915
|
const tabId2 = await session.ensureTargetRegistered(existing.targetId);
|
|
7601
7916
|
const pageSession2 = await session.getPageSession(tabId2);
|
|
7602
7917
|
await ensureControlledIndicator(pageSession2, controlSource);
|
|
7918
|
+
const capture2 = currentCapture(pageSession2);
|
|
7603
7919
|
return {
|
|
7604
7920
|
tabId: tabId2,
|
|
7605
7921
|
url: existing.url ?? url2,
|
|
7606
7922
|
title: existing.title ?? "",
|
|
7607
7923
|
opened: false,
|
|
7608
|
-
reused: true
|
|
7924
|
+
reused: true,
|
|
7925
|
+
capture: capture2
|
|
7609
7926
|
};
|
|
7610
7927
|
}
|
|
7611
7928
|
if (reuse === "require") {
|
|
@@ -7620,6 +7937,7 @@ async function cdpTabOpen(session, data, controlSource = "local") {
|
|
|
7620
7937
|
const tabId = await session.registerTarget(targetId);
|
|
7621
7938
|
const pageSession = await session.getPageSession(tabId);
|
|
7622
7939
|
await ensureControlledIndicator(pageSession, controlSource);
|
|
7940
|
+
const capture = currentCapture(pageSession);
|
|
7623
7941
|
if (emulationConfig) {
|
|
7624
7942
|
for (const { method, params } of buildEnableEmulationCommands(emulationConfig)) {
|
|
7625
7943
|
await pageSession.client.sendCommand(method, params);
|
|
@@ -7638,6 +7956,7 @@ async function cdpTabOpen(session, data, controlSource = "local") {
|
|
|
7638
7956
|
title: targetInfo?.title ?? "",
|
|
7639
7957
|
opened: true,
|
|
7640
7958
|
reused: false,
|
|
7959
|
+
capture,
|
|
7641
7960
|
...emulationConfig && {
|
|
7642
7961
|
emulation: {
|
|
7643
7962
|
preset: emulationConfig.presetName,
|
|
@@ -9433,7 +9752,7 @@ import os2 from "node:os";
|
|
|
9433
9752
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
9434
9753
|
|
|
9435
9754
|
// src/version.ts
|
|
9436
|
-
var NATIVE_HOST_VERSION = true ? "2.
|
|
9755
|
+
var NATIVE_HOST_VERSION = true ? "2.3.0" : "unknown";
|
|
9437
9756
|
|
|
9438
9757
|
// src/analytics.ts
|
|
9439
9758
|
var MEASUREMENT_ID = "G-W84LJDZ6PH";
|
|
@@ -10294,13 +10613,13 @@ var AgentChatManager = class {
|
|
|
10294
10613
|
|
|
10295
10614
|
// src/agent/codex-provider.ts
|
|
10296
10615
|
import os3 from "node:os";
|
|
10297
|
-
import path7 from "node:path";
|
|
10298
10616
|
import readline from "node:readline";
|
|
10299
10617
|
import { spawn as spawn6 } from "node:child_process";
|
|
10300
10618
|
|
|
10301
10619
|
// src/agent/executable-resolver.ts
|
|
10302
10620
|
import fs6 from "node:fs";
|
|
10303
10621
|
import { spawn as spawn5 } from "node:child_process";
|
|
10622
|
+
import path7 from "node:path";
|
|
10304
10623
|
|
|
10305
10624
|
// ../setup/dist/process.js
|
|
10306
10625
|
import fs5 from "node:fs";
|
|
@@ -10317,6 +10636,27 @@ function isExecutable(filePath, platform = process.platform) {
|
|
|
10317
10636
|
function executableNames(name, platform = process.platform) {
|
|
10318
10637
|
return platform === "win32" ? [`${name}.cmd`, `${name}.exe`, name] : [name];
|
|
10319
10638
|
}
|
|
10639
|
+
function versionManagerExecutableCandidates(home, names, options = {}) {
|
|
10640
|
+
const env = options.env ?? process.env;
|
|
10641
|
+
const platform = options.platform ?? process.platform;
|
|
10642
|
+
const readdirSync2 = options.readdirSync ?? fs5.readdirSync;
|
|
10643
|
+
const fnmDefaultRoot = env.XDG_DATA_HOME ? path6.join(env.XDG_DATA_HOME, "fnm") : platform === "darwin" ? path6.join(home, "Library", "Application Support", "fnm") : platform === "win32" && env.APPDATA ? path6.join(env.APPDATA, "fnm") : path6.join(home, ".local", "share", "fnm");
|
|
10644
|
+
const roots = [
|
|
10645
|
+
path6.join(env.NVM_DIR || path6.join(home, ".nvm"), "versions", "node"),
|
|
10646
|
+
path6.join(env.FNM_DIR || fnmDefaultRoot, "node-versions"),
|
|
10647
|
+
path6.join(home, ".fnm", "node-versions")
|
|
10648
|
+
].filter((root, index, all) => all.indexOf(root) === index);
|
|
10649
|
+
return roots.flatMap((root) => {
|
|
10650
|
+
try {
|
|
10651
|
+
return readdirSync2(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).sort((left, right) => right.name.localeCompare(left.name, void 0, { numeric: true })).flatMap((entry) => names.flatMap((name) => [
|
|
10652
|
+
path6.join(root, entry.name, "bin", name),
|
|
10653
|
+
path6.join(root, entry.name, "installation", "bin", name)
|
|
10654
|
+
]));
|
|
10655
|
+
} catch {
|
|
10656
|
+
return [];
|
|
10657
|
+
}
|
|
10658
|
+
});
|
|
10659
|
+
}
|
|
10320
10660
|
function resolveSpawnCommand(executable, args, platform = process.platform, commandInterpreter = process.env.ComSpec) {
|
|
10321
10661
|
if (platform === "win32" && /\.(?:cmd|bat)$/i.test(executable)) {
|
|
10322
10662
|
return {
|
|
@@ -10344,6 +10684,46 @@ function prependPath(directory, env) {
|
|
|
10344
10684
|
}
|
|
10345
10685
|
|
|
10346
10686
|
// src/agent/executable-resolver.ts
|
|
10687
|
+
function agentExecutableCandidatePaths({
|
|
10688
|
+
executableNames: executableNames2,
|
|
10689
|
+
configuredPath,
|
|
10690
|
+
env = process.env,
|
|
10691
|
+
extraUserCandidates = [],
|
|
10692
|
+
home,
|
|
10693
|
+
platform = process.platform,
|
|
10694
|
+
processExecPath = process.execPath,
|
|
10695
|
+
readdirSync: readdirSync2
|
|
10696
|
+
}) {
|
|
10697
|
+
const pathKey = Object.keys(env).find((key) => key.toLowerCase() === "path") || "PATH";
|
|
10698
|
+
const pathCandidates = (env[pathKey] || "").split(path7.delimiter).filter(Boolean).flatMap((directory) => executableNames2.map((name) => path7.join(directory, name)));
|
|
10699
|
+
const commonUserDirectories = [
|
|
10700
|
+
path7.join(home, ".local", "bin"),
|
|
10701
|
+
path7.join(home, ".npm-global", "bin"),
|
|
10702
|
+
path7.join(home, ".volta", "bin"),
|
|
10703
|
+
path7.join(home, ".local", "share", "pnpm"),
|
|
10704
|
+
path7.join(home, "Library", "pnpm"),
|
|
10705
|
+
path7.join(home, ".bun", "bin"),
|
|
10706
|
+
...platform === "win32" && env.APPDATA ? [path7.join(env.APPDATA, "npm")] : []
|
|
10707
|
+
];
|
|
10708
|
+
const systemDirectories = platform === "win32" ? [] : ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin"];
|
|
10709
|
+
return [
|
|
10710
|
+
configuredPath,
|
|
10711
|
+
...executableNames2.map((name) => path7.join(path7.dirname(processExecPath), name)),
|
|
10712
|
+
...commonUserDirectories.flatMap(
|
|
10713
|
+
(directory) => executableNames2.map((name) => path7.join(directory, name))
|
|
10714
|
+
),
|
|
10715
|
+
...extraUserCandidates,
|
|
10716
|
+
...versionManagerExecutableCandidates(home, executableNames2, {
|
|
10717
|
+
env,
|
|
10718
|
+
platform,
|
|
10719
|
+
readdirSync: readdirSync2
|
|
10720
|
+
}),
|
|
10721
|
+
...systemDirectories.flatMap(
|
|
10722
|
+
(directory) => executableNames2.map((name) => path7.join(directory, name))
|
|
10723
|
+
),
|
|
10724
|
+
...pathCandidates
|
|
10725
|
+
].filter((candidate) => typeof candidate === "string");
|
|
10726
|
+
}
|
|
10347
10727
|
var AgentExecutableResolver = class {
|
|
10348
10728
|
constructor(options) {
|
|
10349
10729
|
this.options = options;
|
|
@@ -10457,6 +10837,21 @@ var REQUEST_TIMEOUT_MS = 3e4;
|
|
|
10457
10837
|
var PROBE_TIMEOUT_MS = 5e3;
|
|
10458
10838
|
var MAX_MODEL_CHARS = 256;
|
|
10459
10839
|
var CODEX_NOT_FOUND_ERROR = "Codex CLI was not found. Install @openai/codex or set MEARL_CODEX_PATH.";
|
|
10840
|
+
function codexExecutableCandidatePaths(options = {}) {
|
|
10841
|
+
const env = options.env ?? process.env;
|
|
10842
|
+
const home = (options.homedir ?? os3.homedir)();
|
|
10843
|
+
const platform = options.platform ?? process.platform;
|
|
10844
|
+
const executableName = platform === "win32" ? "codex.cmd" : "codex";
|
|
10845
|
+
return agentExecutableCandidatePaths({
|
|
10846
|
+
executableNames: [executableName],
|
|
10847
|
+
configuredPath: env.MEARL_CODEX_PATH,
|
|
10848
|
+
env,
|
|
10849
|
+
home,
|
|
10850
|
+
platform,
|
|
10851
|
+
processExecPath: options.processExecPath,
|
|
10852
|
+
readdirSync: options.readdirSync
|
|
10853
|
+
});
|
|
10854
|
+
}
|
|
10460
10855
|
function codexModelInfo(value) {
|
|
10461
10856
|
if (typeof value !== "string") return void 0;
|
|
10462
10857
|
const id = value.trim().slice(0, MAX_MODEL_CHARS);
|
|
@@ -10938,18 +11333,7 @@ var CodexAgentProvider = class {
|
|
|
10938
11333
|
return this.executableResolver.resolve();
|
|
10939
11334
|
}
|
|
10940
11335
|
resolveExecutableCandidates() {
|
|
10941
|
-
|
|
10942
|
-
const configured = process.env.MEARL_CODEX_PATH;
|
|
10943
|
-
const pathCandidates = (process.env.PATH || "").split(path7.delimiter).filter(Boolean).map((dir) => path7.join(dir, executableName));
|
|
10944
|
-
return executableFileCandidates([
|
|
10945
|
-
configured,
|
|
10946
|
-
path7.join(path7.dirname(process.execPath), executableName),
|
|
10947
|
-
path7.join(os3.homedir(), ".local", "bin", executableName),
|
|
10948
|
-
path7.join(os3.homedir(), ".npm-global", "bin", executableName),
|
|
10949
|
-
path7.join(os3.homedir(), ".volta", "bin", executableName),
|
|
10950
|
-
...process.platform === "win32" ? [] : ["/opt/homebrew/bin/codex", "/usr/local/bin/codex", "/usr/bin/codex"],
|
|
10951
|
-
...pathCandidates
|
|
10952
|
-
]);
|
|
11336
|
+
return executableFileCandidates(codexExecutableCandidatePaths());
|
|
10953
11337
|
}
|
|
10954
11338
|
};
|
|
10955
11339
|
|
|
@@ -28303,10 +28687,10 @@ function parseQoderSkillsList(output, cwd, home = os4.homedir()) {
|
|
|
28303
28687
|
finish();
|
|
28304
28688
|
return skills;
|
|
28305
28689
|
}
|
|
28306
|
-
function qoderManagedExecutableCandidates(home) {
|
|
28690
|
+
function qoderManagedExecutableCandidates(home, readdirSync2 = fs7.readdirSync) {
|
|
28307
28691
|
const directory = path8.join(home, ".qoder", "bin", "qodercli");
|
|
28308
28692
|
try {
|
|
28309
|
-
return
|
|
28693
|
+
return readdirSync2(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.startsWith("qodercli-")).sort((left, right) => right.name.localeCompare(left.name, void 0, { numeric: true })).map((entry) => path8.join(directory, entry.name));
|
|
28310
28694
|
} catch {
|
|
28311
28695
|
return [];
|
|
28312
28696
|
}
|
|
@@ -28321,6 +28705,25 @@ function isPermissionResponse(value) {
|
|
|
28321
28705
|
function qoderInstallCommand(platform = process.platform) {
|
|
28322
28706
|
return platform === "win32" ? "npm install -g @qoder-ai/qodercli" : "curl -fsSL https://qoder.com/install | bash";
|
|
28323
28707
|
}
|
|
28708
|
+
function qoderExecutableCandidatePaths(options = {}) {
|
|
28709
|
+
const env = options.env ?? process.env;
|
|
28710
|
+
const home = (options.homedir ?? os4.homedir)();
|
|
28711
|
+
const platform = options.platform ?? process.platform;
|
|
28712
|
+
const executableNames2 = platform === "win32" ? ["qodercli.exe", "qodercli.cmd"] : ["qodercli"];
|
|
28713
|
+
return agentExecutableCandidatePaths({
|
|
28714
|
+
executableNames: executableNames2,
|
|
28715
|
+
configuredPath: env.MEARL_QODER_PATH,
|
|
28716
|
+
env,
|
|
28717
|
+
extraUserCandidates: [
|
|
28718
|
+
...qoderManagedExecutableCandidates(home, options.readdirSync),
|
|
28719
|
+
...executableNames2.map((name) => path8.join(home, ".qoder", "bin", name))
|
|
28720
|
+
],
|
|
28721
|
+
home,
|
|
28722
|
+
platform,
|
|
28723
|
+
processExecPath: options.processExecPath,
|
|
28724
|
+
readdirSync: options.readdirSync
|
|
28725
|
+
});
|
|
28726
|
+
}
|
|
28324
28727
|
function sessionOptions(options) {
|
|
28325
28728
|
const cwd = path8.resolve(options.cwd || os4.homedir());
|
|
28326
28729
|
return {
|
|
@@ -29112,19 +29515,7 @@ ${message}` : message;
|
|
|
29112
29515
|
return this.executableResolver.resolve();
|
|
29113
29516
|
}
|
|
29114
29517
|
resolveExecutableCandidates() {
|
|
29115
|
-
|
|
29116
|
-
const configured = process.env.MEARL_QODER_PATH;
|
|
29117
|
-
const home = os4.homedir();
|
|
29118
|
-
const pathCandidates = (process.env.PATH || "").split(path8.delimiter).filter(Boolean).flatMap((dir) => executableNames2.map((name) => path8.join(dir, name)));
|
|
29119
|
-
return executableFileCandidates([
|
|
29120
|
-
configured,
|
|
29121
|
-
...executableNames2.map((name) => path8.join(path8.dirname(process.execPath), name)),
|
|
29122
|
-
...executableNames2.map((name) => path8.join(home, ".local", "bin", name)),
|
|
29123
|
-
...qoderManagedExecutableCandidates(home),
|
|
29124
|
-
...executableNames2.map((name) => path8.join(home, ".qoder", "bin", name)),
|
|
29125
|
-
...process.platform === "win32" ? [] : ["/opt/homebrew/bin/qodercli", "/usr/local/bin/qodercli", "/usr/bin/qodercli"],
|
|
29126
|
-
...pathCandidates
|
|
29127
|
-
]);
|
|
29518
|
+
return executableFileCandidates(qoderExecutableCandidatePaths());
|
|
29128
29519
|
}
|
|
29129
29520
|
emit(event) {
|
|
29130
29521
|
for (const listener of this.listeners) listener(event);
|
|
@@ -29142,22 +29533,6 @@ var ANSI_ESCAPE_PATTERN = new RegExp(String.raw`\u001B\[[0-?]*[ -/]*[@-~]`, "g")
|
|
|
29142
29533
|
function existingExecutable(candidates, existsSync4) {
|
|
29143
29534
|
return candidates.find((candidate) => candidate && existsSync4(candidate)) ?? null;
|
|
29144
29535
|
}
|
|
29145
|
-
function versionManagerCandidates(home, executableNames2, readdirSync2) {
|
|
29146
|
-
const roots = [
|
|
29147
|
-
path9.join(home, ".nvm", "versions", "node"),
|
|
29148
|
-
path9.join(home, ".fnm", "node-versions")
|
|
29149
|
-
];
|
|
29150
|
-
return roots.flatMap((root) => {
|
|
29151
|
-
try {
|
|
29152
|
-
return readdirSync2(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).sort((left, right) => right.name.localeCompare(left.name, void 0, { numeric: true })).flatMap((entry) => executableNames2.flatMap((name) => [
|
|
29153
|
-
path9.join(root, entry.name, "bin", name),
|
|
29154
|
-
path9.join(root, entry.name, "installation", "bin", name)
|
|
29155
|
-
]));
|
|
29156
|
-
} catch {
|
|
29157
|
-
return [];
|
|
29158
|
-
}
|
|
29159
|
-
});
|
|
29160
|
-
}
|
|
29161
29536
|
function stripAnsi(value) {
|
|
29162
29537
|
return value.replace(ANSI_ESCAPE_PATTERN, "");
|
|
29163
29538
|
}
|
|
@@ -29179,7 +29554,11 @@ function resolveAliSkillsExecutable(options = {}) {
|
|
|
29179
29554
|
...names.map((name) => path9.join(home, ".volta", "bin", name)),
|
|
29180
29555
|
...names.map((name) => path9.join(home, ".local", "share", "pnpm", name)),
|
|
29181
29556
|
...names.map((name) => path9.join(home, "Library", "pnpm", name)),
|
|
29182
|
-
...
|
|
29557
|
+
...versionManagerExecutableCandidates(home, names, {
|
|
29558
|
+
env,
|
|
29559
|
+
platform,
|
|
29560
|
+
readdirSync: readdirSync2
|
|
29561
|
+
}),
|
|
29183
29562
|
...platform === "win32" ? [] : ["/opt/homebrew/bin/ali-skills", "/usr/local/bin/ali-skills", "/usr/bin/ali-skills"],
|
|
29184
29563
|
...pathCandidates
|
|
29185
29564
|
];
|