@ada-mcp/mcp-server 0.1.8 → 0.1.10
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/cli.cjs +107 -38
- package/package.json +2 -2
- package/scripts/preinstall-probes.mjs +5 -1
package/dist/cli.cjs
CHANGED
|
@@ -3568,6 +3568,39 @@ function resolveBundledPlaywrightCli() {
|
|
|
3568
3568
|
const version = String(JSON.parse(raw).version ?? "");
|
|
3569
3569
|
return { command: "node", cliArgs: [import_node_path5.default.join(root, "cli.js")], version };
|
|
3570
3570
|
}
|
|
3571
|
+
function resolveChromiumBrowserVersion() {
|
|
3572
|
+
try {
|
|
3573
|
+
const browsersPath = require2.resolve("playwright-core/browsers.json");
|
|
3574
|
+
const raw = (0, import_node_fs.readFileSync)(browsersPath, "utf8");
|
|
3575
|
+
const parsed = JSON.parse(raw);
|
|
3576
|
+
const chromium = parsed.browsers?.find((b) => b.name === "chromium");
|
|
3577
|
+
return String(chromium?.browserVersion ?? "").trim();
|
|
3578
|
+
} catch {
|
|
3579
|
+
return "";
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
function playwrightChromiumZipUrl(host, browserVersion) {
|
|
3583
|
+
const h = normalizeHostUrl(host);
|
|
3584
|
+
const base = h.includes("cdn.npmmirror.com/binaries/playwright") || h.endsWith("/binaries/playwright") ? "https://cdn.npmmirror.com/binaries/playwright" : h.includes("npmmirror.com") && !h.includes("/mirrors/playwright") ? "https://npmmirror.com/mirrors/playwright" : h;
|
|
3585
|
+
return `${base}/builds/cft/${browserVersion}/win64/chrome-win64.zip`;
|
|
3586
|
+
}
|
|
3587
|
+
async function probePlaywrightBrowserArtifact(host, browserVersion) {
|
|
3588
|
+
const url = playwrightChromiumZipUrl(host, browserVersion);
|
|
3589
|
+
const started = Date.now();
|
|
3590
|
+
const controller = new AbortController();
|
|
3591
|
+
const timer = setTimeout(() => controller.abort(), 8e3);
|
|
3592
|
+
try {
|
|
3593
|
+
const response = await fetch(url, { method: "HEAD", redirect: "follow", signal: controller.signal });
|
|
3594
|
+
if (response.status === 200) {
|
|
3595
|
+
return Date.now() - started;
|
|
3596
|
+
}
|
|
3597
|
+
return null;
|
|
3598
|
+
} catch {
|
|
3599
|
+
return null;
|
|
3600
|
+
} finally {
|
|
3601
|
+
clearTimeout(timer);
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3571
3604
|
function requiredAppiumDrivers(config) {
|
|
3572
3605
|
return Array.from(new Set(config.appium.requiredDrivers ?? []));
|
|
3573
3606
|
}
|
|
@@ -3677,7 +3710,6 @@ async function resolveCompatibleDriverSpecs(driver) {
|
|
|
3677
3710
|
return Array.from(new Set(specs));
|
|
3678
3711
|
}
|
|
3679
3712
|
var detectedBestRegistryByKey = /* @__PURE__ */ new Map();
|
|
3680
|
-
var detectedBestPlaywrightHost = null;
|
|
3681
3713
|
var PROGRESS_STEPS = [
|
|
3682
3714
|
"deps.ensure.start",
|
|
3683
3715
|
"registry.probe.start",
|
|
@@ -3859,40 +3891,43 @@ async function probePlaywrightHostLatency(host) {
|
|
|
3859
3891
|
}
|
|
3860
3892
|
return best;
|
|
3861
3893
|
}
|
|
3862
|
-
async function
|
|
3863
|
-
if (detectedBestPlaywrightHost) {
|
|
3864
|
-
return detectedBestPlaywrightHost;
|
|
3865
|
-
}
|
|
3894
|
+
async function rankPlaywrightHosts(config) {
|
|
3866
3895
|
const candidates = playwrightHostCandidates(config);
|
|
3867
|
-
|
|
3896
|
+
const browserVersion = resolveChromiumBrowserVersion();
|
|
3897
|
+
progress("playwright.host.probe.start", { candidates, browserVersion: browserVersion || void 0 });
|
|
3868
3898
|
const probeResults = await Promise.all(candidates.map(async (candidate) => {
|
|
3869
3899
|
progress("playwright.host.probe.try", { candidate });
|
|
3870
|
-
const
|
|
3871
|
-
|
|
3872
|
-
|
|
3900
|
+
const artifactLatency = browserVersion ? await probePlaywrightBrowserArtifact(candidate, browserVersion) : null;
|
|
3901
|
+
const rootLatency = await probePlaywrightHostLatency(candidate);
|
|
3902
|
+
const latency = artifactLatency ?? rootLatency;
|
|
3903
|
+
const artifactOk = artifactLatency !== null;
|
|
3904
|
+
progress("playwright.host.probe.result", {
|
|
3905
|
+
candidate,
|
|
3906
|
+
latencyMs: latency,
|
|
3907
|
+
artifactOk,
|
|
3908
|
+
browserVersion: browserVersion || void 0
|
|
3909
|
+
});
|
|
3910
|
+
return { candidate, latency, artifactOk, priority: playwrightHostPriorityIndex(candidates, candidate) };
|
|
3873
3911
|
}));
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
if (
|
|
3879
|
-
|
|
3880
|
-
const priority = playwrightHostPriorityIndex(candidates, candidate);
|
|
3881
|
-
if (latency < bestLatency || latency === bestLatency && priority < bestPriority) {
|
|
3882
|
-
best = candidate;
|
|
3883
|
-
bestLatency = latency;
|
|
3884
|
-
bestPriority = priority;
|
|
3912
|
+
const reachable = probeResults.filter((x) => x.latency !== null);
|
|
3913
|
+
const withArtifact = reachable.filter((x) => x.artifactOk);
|
|
3914
|
+
const pool = withArtifact.length > 0 ? withArtifact : reachable;
|
|
3915
|
+
pool.sort((a, b) => {
|
|
3916
|
+
if (a.artifactOk !== b.artifactOk) {
|
|
3917
|
+
return a.artifactOk ? -1 : 1;
|
|
3885
3918
|
}
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
log("info", {
|
|
3889
|
-
event: "deps.playwright.host.auto-selected",
|
|
3890
|
-
details: {
|
|
3891
|
-
selected: best,
|
|
3892
|
-
candidates
|
|
3919
|
+
if (a.latency !== b.latency) {
|
|
3920
|
+
return (a.latency ?? 0) - (b.latency ?? 0);
|
|
3893
3921
|
}
|
|
3922
|
+
return a.priority - b.priority;
|
|
3894
3923
|
});
|
|
3895
|
-
|
|
3924
|
+
const ranked = pool.map((x) => x.candidate);
|
|
3925
|
+
for (const candidate of candidates) {
|
|
3926
|
+
if (!ranked.includes(candidate)) {
|
|
3927
|
+
ranked.push(candidate);
|
|
3928
|
+
}
|
|
3929
|
+
}
|
|
3930
|
+
return ranked.length > 0 ? ranked : [...candidates];
|
|
3896
3931
|
}
|
|
3897
3932
|
async function runInstallWithPriority(config, packages, onLogLine) {
|
|
3898
3933
|
const npmProxy = await detectBestRegistry(config, npmProxyRegistry());
|
|
@@ -4035,16 +4070,37 @@ async function installPlaywrightBrowser(config, onLogLine, options) {
|
|
|
4035
4070
|
if (targets.length > 0) {
|
|
4036
4071
|
installArgs.push(...targets);
|
|
4037
4072
|
}
|
|
4038
|
-
const
|
|
4039
|
-
onLogLine?.(`[playwright] \u4F7F\u7528\u5185\u7F6E playwright@${version} CLI\uFF0C\u955C\u50CF ${selectedHost}\uFF0C\u76EE\u6807: ${targets.length ? targets.join(",") : "all"}${options?.force ? " (--force)" : ""}`);
|
|
4073
|
+
const rankedHosts = await rankPlaywrightHosts(config);
|
|
4040
4074
|
const timeoutMs = playwrightInstallTimeoutMs();
|
|
4041
4075
|
onLogLine?.(`[playwright] \u5B89\u88C5\u8D85\u65F6\u4E0A\u9650 ${Math.round(timeoutMs / 1e3)}s\uFF08\u53EF\u7528 ADA_PLAYWRIGHT_INSTALL_TIMEOUT_MS \u8C03\u6574\uFF09`);
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4076
|
+
let lastError;
|
|
4077
|
+
for (let i = 0; i < rankedHosts.length; i++) {
|
|
4078
|
+
const host = rankedHosts[i];
|
|
4079
|
+
if (i > 0) {
|
|
4080
|
+
onLogLine?.(`[playwright] \u4E0A\u4E00\u955C\u50CF\u5931\u8D25\uFF0C\u6539\u8BD5 ${host}`);
|
|
4081
|
+
}
|
|
4082
|
+
onLogLine?.(`[playwright] \u4F7F\u7528\u5185\u7F6E playwright@${version} CLI\uFF0C\u955C\u50CF ${host}\uFF0C\u76EE\u6807: ${targets.length ? targets.join(",") : "all"}${options?.force ? " (--force)" : ""}`);
|
|
4083
|
+
try {
|
|
4084
|
+
await runCommand2(command, installArgs, {
|
|
4085
|
+
env: { PLAYWRIGHT_DOWNLOAD_HOST: host },
|
|
4086
|
+
timeoutMs,
|
|
4087
|
+
onLogLine
|
|
4088
|
+
});
|
|
4089
|
+
progress("playwright.browser.install.done", { selectedHost: host, attempt: i + 1 });
|
|
4090
|
+
return;
|
|
4091
|
+
} catch (error) {
|
|
4092
|
+
lastError = error;
|
|
4093
|
+
log("warn", {
|
|
4094
|
+
event: "deps.playwright.browser.install.host.fail",
|
|
4095
|
+
details: {
|
|
4096
|
+
host,
|
|
4097
|
+
attempt: i + 1,
|
|
4098
|
+
message: error instanceof Error ? error.message : String(error)
|
|
4099
|
+
}
|
|
4100
|
+
});
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
throw lastError instanceof Error ? lastError : new Error(String(lastError ?? "playwright browser install failed"));
|
|
4048
4104
|
}
|
|
4049
4105
|
async function checkPlaywrightLaunchable() {
|
|
4050
4106
|
try {
|
|
@@ -6624,6 +6680,13 @@ function resolveBootstrapInstallDeps(argv2) {
|
|
|
6624
6680
|
if (nativeDir) extras.nativeDriversDir = nativeDir;
|
|
6625
6681
|
return { skip: false, scopes, force, extras };
|
|
6626
6682
|
}
|
|
6683
|
+
var PREINSTALL_PLAYWRIGHT_HOST_ALLOW = /* @__PURE__ */ new Set([
|
|
6684
|
+
"https://cdn.playwright.dev",
|
|
6685
|
+
"https://playwright.azureedge.net"
|
|
6686
|
+
]);
|
|
6687
|
+
function normalizePlaywrightHost(url) {
|
|
6688
|
+
return url.replace(/\/$/, "");
|
|
6689
|
+
}
|
|
6627
6690
|
function applyPreinstallPlaywrightHostFile() {
|
|
6628
6691
|
if (process.env.PLAYWRIGHT_DOWNLOAD_HOST?.trim()) {
|
|
6629
6692
|
return;
|
|
@@ -6634,12 +6697,18 @@ function applyPreinstallPlaywrightHostFile() {
|
|
|
6634
6697
|
for (const root of roots) {
|
|
6635
6698
|
const file = import_node_path10.default.join(root, ".ada-mcp-playwright-host");
|
|
6636
6699
|
try {
|
|
6637
|
-
const host = import_node_fs3.default.readFileSync(file, "utf8").trim();
|
|
6638
|
-
if (host.length > 0) {
|
|
6700
|
+
const host = normalizePlaywrightHost(import_node_fs3.default.readFileSync(file, "utf8").trim());
|
|
6701
|
+
if (host.length > 0 && PREINSTALL_PLAYWRIGHT_HOST_ALLOW.has(host)) {
|
|
6639
6702
|
process.env.PLAYWRIGHT_DOWNLOAD_HOST = host;
|
|
6640
6703
|
console.error(`[ADA-MCP] using playwright CDN from ${file}: ${host}`);
|
|
6641
6704
|
return;
|
|
6642
6705
|
}
|
|
6706
|
+
if (host.length > 0) {
|
|
6707
|
+
console.error(
|
|
6708
|
+
`[ADA-MCP] ignore preinstall playwright CDN (runtime will re-probe): ${host}`
|
|
6709
|
+
);
|
|
6710
|
+
return;
|
|
6711
|
+
}
|
|
6643
6712
|
} catch {
|
|
6644
6713
|
}
|
|
6645
6714
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ada-mcp/mcp-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "ADA MCP server for web/mobile automation (stdio + remote HTTP)",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "commonjs",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"express": "^5.2.1",
|
|
36
36
|
"jimp": "^1.6.0",
|
|
37
37
|
"js-yaml": "^4.1.0",
|
|
38
|
-
"playwright": "
|
|
38
|
+
"playwright": "1.59.1",
|
|
39
39
|
"selenium-webdriver": "^4.34.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
@@ -62,7 +62,11 @@ async function main() {
|
|
|
62
62
|
console.error(`[ada-mcp preinstall] registry ${candidate} -> ${latency === null ? "fail" : `${latency}ms`}`);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
/** preinstall 阶段依赖尚未安装,无法校验浏览器包是否存在;仅测官方 CDN,避免写入国内镜像后 404 */
|
|
66
|
+
const pwCandidates = [
|
|
67
|
+
"https://cdn.playwright.dev",
|
|
68
|
+
"https://playwright.azureedge.net"
|
|
69
|
+
];
|
|
66
70
|
const pw = await detectBestPlaywrightHost(pwCandidates);
|
|
67
71
|
const hostFile = path.join(root, ".ada-mcp-playwright-host");
|
|
68
72
|
fs.writeFileSync(hostFile, `${pw.best}\n`, "utf8");
|