@ada-mcp/mcp-server 0.1.7 → 0.1.8
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/README.md +6 -6
- package/dist/cli.cjs +154 -48
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,25 +8,25 @@ ADA MCP server package that supports:
|
|
|
8
8
|
|
|
9
9
|
## 标准安装(Cursor / MCP)
|
|
10
10
|
|
|
11
|
-
请使用 **`@ada-mcp/launcher@0.1.
|
|
11
|
+
请使用 **`@ada-mcp/launcher@0.1.3`** 拉起本包(见 [launcher README](../ada-mcp-launcher/README.md)):
|
|
12
12
|
|
|
13
13
|
```json
|
|
14
14
|
{
|
|
15
15
|
"mcpServers": {
|
|
16
16
|
"ada-mcp": {
|
|
17
17
|
"command": "pnpm",
|
|
18
|
-
"args": ["dlx", "@ada-mcp/launcher@0.1.
|
|
18
|
+
"args": ["dlx", "@ada-mcp/launcher@0.1.3"]
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
本包版本:**`@ada-mcp/mcp-server@0.1.
|
|
24
|
+
本包版本:**`@ada-mcp/mcp-server@0.1.7`**(由 launcher 默认拉取)。
|
|
25
25
|
|
|
26
26
|
直接调试本包(无 launcher 拉包前测速):
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
pnpm dlx @ada-mcp/mcp-server@0.1.
|
|
29
|
+
pnpm dlx @ada-mcp/mcp-server@0.1.7
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
## 启动时自动安装依赖(默认仅 Playwright)
|
|
@@ -81,12 +81,12 @@ pnpm dlx @ada-mcp/mcp-server@0.1.6
|
|
|
81
81
|
在标准 `args` 后追加,例如安装全部依赖:
|
|
82
82
|
|
|
83
83
|
```json
|
|
84
|
-
"args": ["dlx", "@ada-mcp/launcher@0.1.
|
|
84
|
+
"args": ["dlx", "@ada-mcp/launcher@0.1.3", "--install-deps=all"]
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
## Cursor MCP 配置
|
|
88
88
|
|
|
89
|
-
与上文**标准配置**相同:`pnpm` + `dlx @ada-mcp/launcher@0.1.
|
|
89
|
+
与上文**标准配置**相同:`pnpm` + `dlx @ada-mcp/launcher@0.1.3`。
|
|
90
90
|
|
|
91
91
|
Windows 若找不到 `pnpm`,可写完整路径,例如 `C:\\Users\\<你>\\AppData\\Roaming\\npm\\pnpm.cmd`,或改用 npx:
|
|
92
92
|
|
package/dist/cli.cjs
CHANGED
|
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/bootstrap-deps.ts
|
|
27
|
-
var
|
|
27
|
+
var import_node_fs3 = __toESM(require("node:fs"));
|
|
28
28
|
var import_node_path10 = __toESM(require("node:path"));
|
|
29
29
|
|
|
30
30
|
// ../ada-agent/dist/config.js
|
|
@@ -2720,7 +2720,7 @@ function createJsonLogger(source) {
|
|
|
2720
2720
|
}
|
|
2721
2721
|
|
|
2722
2722
|
// ../ada-agent/dist/bundled-config.generated.js
|
|
2723
|
-
var bundledDefaultConfigYaml = 'agent:\r\n id: "ada-agent-local"\r\n mode: "foreground"\r\n setupOnFirstRun: true\r\n\r\nbootstrapUI:\r\n enabled: true\r\n mode: "auto" # auto | cli | gui\r\n host: "127.0.0.1"\r\n port: 17650\r\n autoOpenBrowser: true\r\n sessionTtlSec: 600\r\n secretsProvider: "auto" # auto | keychain | credman | file\r\n native:\r\n enabled: false\r\n command: "" # e.g. ./bootstrap-ui / .\\bootstrap-ui.exe\r\n args: []\r\n timeoutMs: 120000\r\n fallbackToWeb: true\r\n\r\ntransport:\r\n mode: "auto"\r\n streamProtocol: "websocket"\r\n requestPath: "/api/v1/execute"\r\n healthPath: "/health"\r\n streamPath: "/ws"\r\n requestTimeoutMs: 15000\r\n\r\ngraphics:\r\n enabled: false\r\n fallbackOnSemanticFailure: false\r\n minConfidence: 0.8\r\n\r\nmonitoring:\r\n enabled: false\r\n platforms: ["web", "android", "ios", "harmony"] # \u53EF\u9009\u5B50\u96C6\r\n sampleEvery: 1 # \u6BCF N \u6761\u64CD\u4F5C\u91C7\u6837\u4E00\u6B21\uFF0C1 \u8868\u793A\u5168\u91CF\r\n outputDir: "artifacts/monitoring"\r\n onFailureOnly: false # true \u65F6\u4EC5\u5931\u8D25\u64CD\u4F5C\u6293\u56FE\uFF0C\u6027\u80FD\u66F4\u4F18\r\n groupBySession: true # \u6309 sessionId/requestId \u5206\u5C42\u5F52\u6863\r\n nonBlocking: true # true \u65F6\u76D1\u63A7\u5F02\u6B65\u6267\u884C\uFF0C\u4E0D\u963B\u585E\u4E3B\u94FE\u8DEF\r\n resolution:\r\n maxWidth: 1280\r\n maxHeight: 720\r\n keepAspectRatio: true # \u4FDD\u6301\u6BD4\u4F8B\uFF0C\u907F\u514D\u76D1\u63A7\u56FE\u50CF\u53D8\u5F62\r\n\r\nqueue:\r\n inboxDir: "tasks/inbox"\r\n processedDir: "tasks/processed"\r\n failedDir: "tasks/failed"\r\n pollIntervalMs: 3000\r\n maxFileRetryAttempts: 2\r\n\r\ndependencies:\r\n autoInstallOnStart: true\r\n playwrightBrowser: "chromium" # chromium | firefox | webkit | all\r\n playwrightInstallTargets: ["
|
|
2723
|
+
var bundledDefaultConfigYaml = 'agent:\r\n id: "ada-agent-local"\r\n mode: "foreground"\r\n setupOnFirstRun: true\r\n\r\nbootstrapUI:\r\n enabled: true\r\n mode: "auto" # auto | cli | gui\r\n host: "127.0.0.1"\r\n port: 17650\r\n autoOpenBrowser: true\r\n sessionTtlSec: 600\r\n secretsProvider: "auto" # auto | keychain | credman | file\r\n native:\r\n enabled: false\r\n command: "" # e.g. ./bootstrap-ui / .\\bootstrap-ui.exe\r\n args: []\r\n timeoutMs: 120000\r\n fallbackToWeb: true\r\n\r\ntransport:\r\n mode: "auto"\r\n streamProtocol: "websocket"\r\n requestPath: "/api/v1/execute"\r\n healthPath: "/health"\r\n streamPath: "/ws"\r\n requestTimeoutMs: 15000\r\n\r\ngraphics:\r\n enabled: false\r\n fallbackOnSemanticFailure: false\r\n minConfidence: 0.8\r\n\r\nmonitoring:\r\n enabled: false\r\n platforms: ["web", "android", "ios", "harmony"] # \u53EF\u9009\u5B50\u96C6\r\n sampleEvery: 1 # \u6BCF N \u6761\u64CD\u4F5C\u91C7\u6837\u4E00\u6B21\uFF0C1 \u8868\u793A\u5168\u91CF\r\n outputDir: "artifacts/monitoring"\r\n onFailureOnly: false # true \u65F6\u4EC5\u5931\u8D25\u64CD\u4F5C\u6293\u56FE\uFF0C\u6027\u80FD\u66F4\u4F18\r\n groupBySession: true # \u6309 sessionId/requestId \u5206\u5C42\u5F52\u6863\r\n nonBlocking: true # true \u65F6\u76D1\u63A7\u5F02\u6B65\u6267\u884C\uFF0C\u4E0D\u963B\u585E\u4E3B\u94FE\u8DEF\r\n resolution:\r\n maxWidth: 1280\r\n maxHeight: 720\r\n keepAspectRatio: true # \u4FDD\u6301\u6BD4\u4F8B\uFF0C\u907F\u514D\u76D1\u63A7\u56FE\u50CF\u53D8\u5F62\r\n\r\nqueue:\r\n inboxDir: "tasks/inbox"\r\n processedDir: "tasks/processed"\r\n failedDir: "tasks/failed"\r\n pollIntervalMs: 3000\r\n maxFileRetryAttempts: 2\r\n\r\ndependencies:\r\n autoInstallOnStart: true\r\n playwrightBrowser: "chromium" # chromium | firefox | webkit | all\r\n playwrightInstallTargets: ["chromium"] # chromium | chrome | msedge | firefox | webkit | all\r\n playwrightDownloadHost: "https://cdn.playwright.dev"\r\n # \u56FD\u5185 npm \u955C\u50CF\uFF08\u6309\u4F18\u5148\u7EA7\uFF1Binstall-deps \u542F\u52A8\u65F6\u6D4B\u901F\u9009\u6700\u5FEB\uFF0C\u65E0\u9700\u7528\u6237\u914D\u7F6E\uFF09\r\n npmRegistryCandidates:\r\n - "https://registry.npmmirror.com" # \u963F\u91CC\u4E91 / npmmirror\uFF08\u63A8\u8350\uFF09\r\n - "https://mirrors.cloud.tencent.com/npm" # \u817E\u8BAF\u4E91\r\n - "https://repo.huaweicloud.com/repository/npm" # \u534E\u4E3A\u4E91\r\n - "https://registry.npmjs.org" # \u5B98\u65B9\u515C\u5E95\r\n playwrightHostCandidates:\r\n - "https://cdn.playwright.dev"\r\n - "https://playwright.azureedge.net"\r\n - "https://npmmirror.com/mirrors/playwright"\r\n - "https://cdn.npmmirror.com/binaries/playwright"\r\n # \u539F\u751F WebDriver\uFF08geckodriver / chromedriver\uFF09\u7EDF\u4E00\u653E\u5728\u9879\u76EE dirver \u76EE\u5F55\r\n nativeDriversDir: "dirver"\r\n geckodriverVersion: "latest" # \u5982 0.36.0\uFF1Binstall-deps --only=selenium \u65F6\u4E0B\u8F7D\u5230\u6B64\u76EE\u5F55\r\n chromedriverVersion: "latest" # \u5982 137\u3001135\u3001match-chrome\uFF08\u5339\u914D\u672C\u673A Chrome \u4E3B\u7248\u672C\uFF09\r\n\r\nappium:\r\n serverUrl: "http://127.0.0.1:4723"\r\n requiredDrivers: ["uiautomator2", "xcuitest", "harmonyos"]\r\n';
|
|
2724
2724
|
|
|
2725
2725
|
// ../ada-agent/dist/config.js
|
|
2726
2726
|
var DEFAULT_CONFIG_RELATIVE = import_node_path2.default.join("config", "default.yaml");
|
|
@@ -2785,8 +2785,8 @@ var defaultConfig = {
|
|
|
2785
2785
|
dependencies: {
|
|
2786
2786
|
autoInstallOnStart: true,
|
|
2787
2787
|
playwrightBrowser: "chromium",
|
|
2788
|
-
playwrightInstallTargets: ["
|
|
2789
|
-
playwrightDownloadHost: "https://
|
|
2788
|
+
playwrightInstallTargets: ["chromium"],
|
|
2789
|
+
playwrightDownloadHost: "https://cdn.playwright.dev",
|
|
2790
2790
|
npmRegistryCandidates: [
|
|
2791
2791
|
"https://registry.npmmirror.com",
|
|
2792
2792
|
"https://mirrors.cloud.tencent.com/npm",
|
|
@@ -2794,8 +2794,10 @@ var defaultConfig = {
|
|
|
2794
2794
|
"https://registry.npmjs.org"
|
|
2795
2795
|
],
|
|
2796
2796
|
playwrightHostCandidates: [
|
|
2797
|
+
"https://cdn.playwright.dev",
|
|
2798
|
+
"https://playwright.azureedge.net",
|
|
2797
2799
|
"https://npmmirror.com/mirrors/playwright",
|
|
2798
|
-
"https://
|
|
2800
|
+
"https://cdn.npmmirror.com/binaries/playwright"
|
|
2799
2801
|
],
|
|
2800
2802
|
nativeDriversDir: "dirver",
|
|
2801
2803
|
geckodriverVersion: "latest",
|
|
@@ -2906,6 +2908,7 @@ async function loadSecret(provider, cwd = process.cwd()) {
|
|
|
2906
2908
|
|
|
2907
2909
|
// ../ada-agent/dist/dependency-installer.js
|
|
2908
2910
|
var import_node_module = require("node:module");
|
|
2911
|
+
var import_node_fs = require("node:fs");
|
|
2909
2912
|
var import_node_child_process2 = require("node:child_process");
|
|
2910
2913
|
var import_promises5 = __toESM(require("node:fs/promises"), 1);
|
|
2911
2914
|
var import_node_path5 = __toESM(require("node:path"), 1);
|
|
@@ -3544,19 +3547,51 @@ function playwrightInstallTargets(config) {
|
|
|
3544
3547
|
const legacy = browserArg(config);
|
|
3545
3548
|
return legacy ? [legacy] : [];
|
|
3546
3549
|
}
|
|
3550
|
+
function expandPlaywrightInstallTargets(targets) {
|
|
3551
|
+
if (targets.length === 0) {
|
|
3552
|
+
return targets;
|
|
3553
|
+
}
|
|
3554
|
+
const lower = targets.map((x) => x.toLowerCase());
|
|
3555
|
+
if (lower.includes("chromium") || lower.includes("firefox") || lower.includes("webkit")) {
|
|
3556
|
+
return lower;
|
|
3557
|
+
}
|
|
3558
|
+
const channelOnly = lower.every((x) => x === "chrome" || x === "msedge");
|
|
3559
|
+
if (channelOnly) {
|
|
3560
|
+
return ["chromium", ...lower];
|
|
3561
|
+
}
|
|
3562
|
+
return lower;
|
|
3563
|
+
}
|
|
3564
|
+
function resolveBundledPlaywrightCli() {
|
|
3565
|
+
const pkgPath = require2.resolve("playwright/package.json");
|
|
3566
|
+
const root = import_node_path5.default.dirname(pkgPath);
|
|
3567
|
+
const raw = (0, import_node_fs.readFileSync)(pkgPath, "utf8");
|
|
3568
|
+
const version = String(JSON.parse(raw).version ?? "");
|
|
3569
|
+
return { command: "node", cliArgs: [import_node_path5.default.join(root, "cli.js")], version };
|
|
3570
|
+
}
|
|
3547
3571
|
function requiredAppiumDrivers(config) {
|
|
3548
3572
|
return Array.from(new Set(config.appium.requiredDrivers ?? []));
|
|
3549
3573
|
}
|
|
3574
|
+
var DEFAULT_NPM_REGISTRY_CANDIDATES = [
|
|
3575
|
+
"https://registry.npmmirror.com",
|
|
3576
|
+
"https://mirrors.cloud.tencent.com/npm",
|
|
3577
|
+
"https://repo.huaweicloud.com/repository/npm",
|
|
3578
|
+
"https://registry.npmjs.org"
|
|
3579
|
+
];
|
|
3550
3580
|
function npmProxyRegistry() {
|
|
3551
|
-
return process.env.ADA_NPM_PROXY_REGISTRY ??
|
|
3581
|
+
return process.env.ADA_NPM_PROXY_REGISTRY ?? DEFAULT_NPM_REGISTRY_CANDIDATES[0];
|
|
3552
3582
|
}
|
|
3553
3583
|
function pnpmProxyRegistry() {
|
|
3554
3584
|
return process.env.ADA_PNPM_PROXY_REGISTRY ?? npmProxyRegistry();
|
|
3555
3585
|
}
|
|
3586
|
+
function parsePositiveMs(raw, fallback) {
|
|
3587
|
+
const parsed = raw ? Number(raw) : fallback;
|
|
3588
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
3589
|
+
}
|
|
3556
3590
|
function installStrategyTimeoutMs() {
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3591
|
+
return parsePositiveMs(process.env.ADA_INSTALL_STRATEGY_TIMEOUT_MS, 12e4);
|
|
3592
|
+
}
|
|
3593
|
+
function playwrightInstallTimeoutMs() {
|
|
3594
|
+
return parsePositiveMs(process.env.ADA_PLAYWRIGHT_INSTALL_TIMEOUT_MS, 9e5);
|
|
3560
3595
|
}
|
|
3561
3596
|
function majorOf(versionLike) {
|
|
3562
3597
|
const text = versionLike.trim().replace(/^v/i, "");
|
|
@@ -3679,10 +3714,23 @@ function normalizeRegistryUrl(url) {
|
|
|
3679
3714
|
}
|
|
3680
3715
|
function registryCandidates(config, baseProxy) {
|
|
3681
3716
|
const primary = normalizeRegistryUrl(baseProxy);
|
|
3682
|
-
const
|
|
3683
|
-
const
|
|
3717
|
+
const fromConfig = Array.isArray(config.dependencies.npmRegistryCandidates) ? config.dependencies.npmRegistryCandidates.map((x) => normalizeRegistryUrl(String(x).trim())).filter(Boolean) : [];
|
|
3718
|
+
const configured = fromConfig.length > 0 ? fromConfig : [...DEFAULT_NPM_REGISTRY_CANDIDATES];
|
|
3684
3719
|
const extra = process.env.ADA_REGISTRY_CANDIDATES ? process.env.ADA_REGISTRY_CANDIDATES.split(",").map((x) => normalizeRegistryUrl(x.trim())).filter(Boolean) : [];
|
|
3685
|
-
|
|
3720
|
+
const ordered = [primary, ...configured, ...extra];
|
|
3721
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3722
|
+
const out = [];
|
|
3723
|
+
for (const url of ordered) {
|
|
3724
|
+
if (!seen.has(url)) {
|
|
3725
|
+
seen.add(url);
|
|
3726
|
+
out.push(url);
|
|
3727
|
+
}
|
|
3728
|
+
}
|
|
3729
|
+
return out;
|
|
3730
|
+
}
|
|
3731
|
+
function registryPriorityIndex(candidates, registry) {
|
|
3732
|
+
const idx = candidates.indexOf(normalizeRegistryUrl(registry));
|
|
3733
|
+
return idx >= 0 ? idx : Number.POSITIVE_INFINITY;
|
|
3686
3734
|
}
|
|
3687
3735
|
async function probeRegistryLatency(registry) {
|
|
3688
3736
|
const target = `${normalizeRegistryUrl(registry)}/appium`;
|
|
@@ -3718,14 +3766,17 @@ async function detectBestRegistry(config, baseProxy) {
|
|
|
3718
3766
|
progress("registry.probe.result", { candidate, latencyMs: latency });
|
|
3719
3767
|
return { candidate, latency };
|
|
3720
3768
|
}));
|
|
3721
|
-
let best = normalizeRegistryUrl(baseProxy);
|
|
3769
|
+
let best = candidates[0] ?? normalizeRegistryUrl(baseProxy);
|
|
3722
3770
|
let bestLatency = Number.POSITIVE_INFINITY;
|
|
3771
|
+
let bestPriority = Number.POSITIVE_INFINITY;
|
|
3723
3772
|
for (const { candidate, latency } of probeResults) {
|
|
3724
3773
|
if (latency === null)
|
|
3725
3774
|
continue;
|
|
3726
|
-
|
|
3775
|
+
const priority = registryPriorityIndex(candidates, candidate);
|
|
3776
|
+
if (latency < bestLatency || latency === bestLatency && priority < bestPriority) {
|
|
3727
3777
|
best = candidate;
|
|
3728
3778
|
bestLatency = latency;
|
|
3779
|
+
bestPriority = priority;
|
|
3729
3780
|
}
|
|
3730
3781
|
}
|
|
3731
3782
|
detectedBestRegistryByKey.set(cacheKey, best);
|
|
@@ -3744,19 +3795,46 @@ function playwrightDownloadHost(config) {
|
|
|
3744
3795
|
function normalizeHostUrl(url) {
|
|
3745
3796
|
return url.replace(/\/$/, "");
|
|
3746
3797
|
}
|
|
3798
|
+
var DEFAULT_PLAYWRIGHT_HOST_CANDIDATES = [
|
|
3799
|
+
"https://cdn.playwright.dev",
|
|
3800
|
+
"https://playwright.azureedge.net",
|
|
3801
|
+
"https://npmmirror.com/mirrors/playwright",
|
|
3802
|
+
"https://cdn.npmmirror.com/binaries/playwright"
|
|
3803
|
+
];
|
|
3804
|
+
var PLAYWRIGHT_HOST_FALLBACK = DEFAULT_PLAYWRIGHT_HOST_CANDIDATES[0];
|
|
3805
|
+
function playwrightProbeUrls(host) {
|
|
3806
|
+
const h = normalizeHostUrl(host);
|
|
3807
|
+
if (h.includes("npmmirror.com/mirrors/playwright")) {
|
|
3808
|
+
return [h, "https://cdn.npmmirror.com/binaries/playwright"];
|
|
3809
|
+
}
|
|
3810
|
+
return [h];
|
|
3811
|
+
}
|
|
3747
3812
|
function playwrightHostCandidates(config) {
|
|
3748
3813
|
const configured = normalizeHostUrl(playwrightDownloadHost(config));
|
|
3749
|
-
const
|
|
3750
|
-
const
|
|
3814
|
+
const fromConfig = Array.isArray(config.dependencies.playwrightHostCandidates) ? config.dependencies.playwrightHostCandidates.map((x) => normalizeHostUrl(String(x).trim())).filter(Boolean) : [];
|
|
3815
|
+
const configuredList = fromConfig.length > 0 ? fromConfig : [...DEFAULT_PLAYWRIGHT_HOST_CANDIDATES];
|
|
3751
3816
|
const extra = process.env.ADA_PLAYWRIGHT_HOST_CANDIDATES ? process.env.ADA_PLAYWRIGHT_HOST_CANDIDATES.split(",").map((x) => normalizeHostUrl(x.trim())).filter(Boolean) : [];
|
|
3752
|
-
|
|
3817
|
+
const ordered = [configured, ...configuredList, ...extra];
|
|
3818
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3819
|
+
const out = [];
|
|
3820
|
+
for (const url of ordered) {
|
|
3821
|
+
if (!seen.has(url)) {
|
|
3822
|
+
seen.add(url);
|
|
3823
|
+
out.push(url);
|
|
3824
|
+
}
|
|
3825
|
+
}
|
|
3826
|
+
return out;
|
|
3753
3827
|
}
|
|
3754
|
-
|
|
3828
|
+
function playwrightHostPriorityIndex(candidates, host) {
|
|
3829
|
+
const idx = candidates.indexOf(normalizeHostUrl(host));
|
|
3830
|
+
return idx >= 0 ? idx : Number.POSITIVE_INFINITY;
|
|
3831
|
+
}
|
|
3832
|
+
async function probeUrlLatency(url) {
|
|
3755
3833
|
const started = Date.now();
|
|
3756
3834
|
const controller = new AbortController();
|
|
3757
3835
|
const timer = setTimeout(() => controller.abort(), 5e3);
|
|
3758
3836
|
try {
|
|
3759
|
-
const response = await fetch(
|
|
3837
|
+
const response = await fetch(url, {
|
|
3760
3838
|
method: "GET",
|
|
3761
3839
|
redirect: "manual",
|
|
3762
3840
|
signal: controller.signal
|
|
@@ -3771,6 +3849,16 @@ async function probeHostLatency(host) {
|
|
|
3771
3849
|
clearTimeout(timer);
|
|
3772
3850
|
}
|
|
3773
3851
|
}
|
|
3852
|
+
async function probePlaywrightHostLatency(host) {
|
|
3853
|
+
let best = null;
|
|
3854
|
+
for (const url of playwrightProbeUrls(host)) {
|
|
3855
|
+
const latency = await probeUrlLatency(url);
|
|
3856
|
+
if (latency !== null && (best === null || latency < best)) {
|
|
3857
|
+
best = latency;
|
|
3858
|
+
}
|
|
3859
|
+
}
|
|
3860
|
+
return best;
|
|
3861
|
+
}
|
|
3774
3862
|
async function detectBestPlaywrightHost(config) {
|
|
3775
3863
|
if (detectedBestPlaywrightHost) {
|
|
3776
3864
|
return detectedBestPlaywrightHost;
|
|
@@ -3779,18 +3867,21 @@ async function detectBestPlaywrightHost(config) {
|
|
|
3779
3867
|
progress("playwright.host.probe.start", { candidates });
|
|
3780
3868
|
const probeResults = await Promise.all(candidates.map(async (candidate) => {
|
|
3781
3869
|
progress("playwright.host.probe.try", { candidate });
|
|
3782
|
-
const latency = await
|
|
3870
|
+
const latency = await probePlaywrightHostLatency(candidate);
|
|
3783
3871
|
progress("playwright.host.probe.result", { candidate, latencyMs: latency });
|
|
3784
3872
|
return { candidate, latency };
|
|
3785
3873
|
}));
|
|
3786
|
-
let best =
|
|
3874
|
+
let best = candidates[0] ?? PLAYWRIGHT_HOST_FALLBACK;
|
|
3787
3875
|
let bestLatency = Number.POSITIVE_INFINITY;
|
|
3876
|
+
let bestPriority = Number.POSITIVE_INFINITY;
|
|
3788
3877
|
for (const { candidate, latency } of probeResults) {
|
|
3789
3878
|
if (latency === null)
|
|
3790
3879
|
continue;
|
|
3791
|
-
|
|
3880
|
+
const priority = playwrightHostPriorityIndex(candidates, candidate);
|
|
3881
|
+
if (latency < bestLatency || latency === bestLatency && priority < bestPriority) {
|
|
3792
3882
|
best = candidate;
|
|
3793
3883
|
bestLatency = latency;
|
|
3884
|
+
bestPriority = priority;
|
|
3794
3885
|
}
|
|
3795
3886
|
}
|
|
3796
3887
|
detectedBestPlaywrightHost = best;
|
|
@@ -3807,7 +3898,7 @@ async function runInstallWithPriority(config, packages, onLogLine) {
|
|
|
3807
3898
|
const npmProxy = await detectBestRegistry(config, npmProxyRegistry());
|
|
3808
3899
|
const pnpmProxy = await detectBestRegistry(config, pnpmProxyRegistry());
|
|
3809
3900
|
progress("packages.install.start", { packages, npmProxy, pnpmProxy });
|
|
3810
|
-
onLogLine?.(`[deps] \u5728\u7EBF\u5B89\u88C5\u5305: ${packages.join(" ")} (\u987A\u5E8F: pnpm -> pnpm-proxy -> npm -> npm-proxy)`);
|
|
3901
|
+
onLogLine?.(`[deps] \u5728\u7EBF\u5B89\u88C5\u5305: ${packages.join(" ")} (registry \u63A2\u6D4B: npm=${npmProxy}, pnpm=${pnpmProxy}\uFF1B\u987A\u5E8F: pnpm -> pnpm-proxy -> npm -> npm-proxy)`);
|
|
3811
3902
|
const strategies = [
|
|
3812
3903
|
{
|
|
3813
3904
|
name: "pnpm",
|
|
@@ -3928,16 +4019,29 @@ async function verifyPlaywrightSelfTest(onLogLine) {
|
|
|
3928
4019
|
await b.close();
|
|
3929
4020
|
}
|
|
3930
4021
|
}
|
|
3931
|
-
async function installPlaywrightBrowser(config, onLogLine) {
|
|
3932
|
-
const
|
|
4022
|
+
async function installPlaywrightBrowser(config, onLogLine, options) {
|
|
4023
|
+
const rawTargets = playwrightInstallTargets(config);
|
|
4024
|
+
const targets = expandPlaywrightInstallTargets(rawTargets);
|
|
4025
|
+
if (rawTargets.length > 0 && targets.length > rawTargets.length) {
|
|
4026
|
+
onLogLine?.("[playwright] \u914D\u7F6E\u4EC5\u542B chrome/msedge \u901A\u9053\uFF0C\u5DF2\u81EA\u52A8\u52A0\u5165 chromium\uFF08\u81EA\u68C0\u9700 Playwright \u5185\u7F6E\u6D4F\u89C8\u5668\uFF09");
|
|
4027
|
+
}
|
|
3933
4028
|
progress("playwright.browser.install.start", { targets: targets.length > 0 ? targets : ["all"] });
|
|
3934
4029
|
onLogLine?.("[playwright] \u5F00\u59CB\u5728\u7EBF\u5B89\u88C5\u6D4F\u89C8\u5668");
|
|
3935
|
-
const
|
|
4030
|
+
const { command, cliArgs, version } = resolveBundledPlaywrightCli();
|
|
4031
|
+
const installArgs = [...cliArgs, "install"];
|
|
4032
|
+
if (options?.force) {
|
|
4033
|
+
installArgs.push("--force");
|
|
4034
|
+
}
|
|
4035
|
+
if (targets.length > 0) {
|
|
4036
|
+
installArgs.push(...targets);
|
|
4037
|
+
}
|
|
3936
4038
|
const selectedHost = await detectBestPlaywrightHost(config);
|
|
3937
|
-
onLogLine?.(`[playwright] \
|
|
3938
|
-
|
|
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)" : ""}`);
|
|
4040
|
+
const timeoutMs = playwrightInstallTimeoutMs();
|
|
4041
|
+
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
|
+
await runCommand2(command, installArgs, {
|
|
3939
4043
|
env: { PLAYWRIGHT_DOWNLOAD_HOST: selectedHost },
|
|
3940
|
-
timeoutMs
|
|
4044
|
+
timeoutMs,
|
|
3941
4045
|
onLogLine
|
|
3942
4046
|
});
|
|
3943
4047
|
progress("playwright.browser.install.done", { selectedHost });
|
|
@@ -4191,7 +4295,9 @@ async function ensureDriverDependencies(config, options) {
|
|
|
4191
4295
|
if (force) {
|
|
4192
4296
|
onLogLine?.(userRequestedBrowserTargets ? "[playwright] --force\uFF1A\u91CD\u65B0\u5B89\u88C5\u5F53\u524D\u52FE\u9009\u7684\u6D4F\u89C8\u5668\u901A\u9053" : "[playwright] --force\uFF1A\u6309\u914D\u7F6E\u6587\u4EF6\u4E2D\u7684\u76EE\u6807\u91CD\u65B0\u5B89\u88C5\u6D4F\u89C8\u5668");
|
|
4193
4297
|
}
|
|
4194
|
-
await installPlaywrightBrowser(configForPlaywright, onLogLine
|
|
4298
|
+
await installPlaywrightBrowser(configForPlaywright, onLogLine, {
|
|
4299
|
+
force: force || reinstallForTargets || !launchOk
|
|
4300
|
+
});
|
|
4195
4301
|
progress("playwright.selfcheck.verify");
|
|
4196
4302
|
await verifyPlaywrightSelfTest(onLogLine);
|
|
4197
4303
|
state.playwrightReady = true;
|
|
@@ -4364,7 +4470,7 @@ function getString(value) {
|
|
|
4364
4470
|
}
|
|
4365
4471
|
|
|
4366
4472
|
// ../../packages/plugin-host/src/index.ts
|
|
4367
|
-
var
|
|
4473
|
+
var import_node_fs2 = __toESM(require("node:fs"), 1);
|
|
4368
4474
|
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
4369
4475
|
var import_node_module2 = require("node:module");
|
|
4370
4476
|
function assertManifest(plugin) {
|
|
@@ -4516,10 +4622,10 @@ function loadPluginFromModule(requireFn, moduleId) {
|
|
|
4516
4622
|
}
|
|
4517
4623
|
}
|
|
4518
4624
|
function registerPluginsFromDirectory(host, pluginDir) {
|
|
4519
|
-
if (!
|
|
4625
|
+
if (!import_node_fs2.default.existsSync(pluginDir)) {
|
|
4520
4626
|
return [];
|
|
4521
4627
|
}
|
|
4522
|
-
const entries =
|
|
4628
|
+
const entries = import_node_fs2.default.readdirSync(pluginDir, { withFileTypes: true }).filter((ent) => ent.isFile() && (ent.name.endsWith(".cjs") || ent.name.endsWith(".js"))).map((ent) => import_node_path6.default.join(pluginDir, ent.name)).sort((a, b) => a.localeCompare(b));
|
|
4523
4629
|
if (entries.length === 0) {
|
|
4524
4630
|
return [];
|
|
4525
4631
|
}
|
|
@@ -4874,7 +4980,7 @@ function normalizePlaywrightTargets(raw) {
|
|
|
4874
4980
|
return { playwrightBrowser: "all", playwrightInstallTargets: ["all"] };
|
|
4875
4981
|
}
|
|
4876
4982
|
if (list.length === 0) {
|
|
4877
|
-
return { playwrightBrowser: "chromium", playwrightInstallTargets: ["
|
|
4983
|
+
return { playwrightBrowser: "chromium", playwrightInstallTargets: ["chromium"] };
|
|
4878
4984
|
}
|
|
4879
4985
|
const ordered = ["chromium", "chrome", "firefox", "webkit", "msedge"].filter((x) => list.includes(x));
|
|
4880
4986
|
const primary = ordered.find((x) => x === "chromium" || x === "firefox" || x === "webkit") ?? "chromium";
|
|
@@ -6528,7 +6634,7 @@ function applyPreinstallPlaywrightHostFile() {
|
|
|
6528
6634
|
for (const root of roots) {
|
|
6529
6635
|
const file = import_node_path10.default.join(root, ".ada-mcp-playwright-host");
|
|
6530
6636
|
try {
|
|
6531
|
-
const host =
|
|
6637
|
+
const host = import_node_fs3.default.readFileSync(file, "utf8").trim();
|
|
6532
6638
|
if (host.length > 0) {
|
|
6533
6639
|
process.env.PLAYWRIGHT_DOWNLOAD_HOST = host;
|
|
6534
6640
|
console.error(`[ADA-MCP] using playwright CDN from ${file}: ${host}`);
|
|
@@ -6567,7 +6673,7 @@ async function runBootstrapInstallDeps(argv2) {
|
|
|
6567
6673
|
|
|
6568
6674
|
// src/main.ts
|
|
6569
6675
|
var import_promises13 = __toESM(require("node:fs/promises"));
|
|
6570
|
-
var
|
|
6676
|
+
var import_node_fs5 = require("node:fs");
|
|
6571
6677
|
var import_node_net2 = __toESM(require("node:net"));
|
|
6572
6678
|
var import_node_path14 = __toESM(require("node:path"));
|
|
6573
6679
|
var import_node_child_process5 = require("node:child_process");
|
|
@@ -6577,7 +6683,7 @@ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
|
6577
6683
|
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
6578
6684
|
|
|
6579
6685
|
// src/executor.ts
|
|
6580
|
-
var
|
|
6686
|
+
var import_node_fs4 = require("node:fs");
|
|
6581
6687
|
var import_node_path11 = __toESM(require("node:path"));
|
|
6582
6688
|
var import_node_url3 = require("node:url");
|
|
6583
6689
|
var import_meta = {};
|
|
@@ -6596,7 +6702,7 @@ function ensureBundledPluginDir() {
|
|
|
6596
6702
|
candidates.push(import_node_path11.default.join(dirname, "..", "plugins"));
|
|
6597
6703
|
}
|
|
6598
6704
|
for (const dir of candidates) {
|
|
6599
|
-
if ((0,
|
|
6705
|
+
if ((0, import_node_fs4.existsSync)(dir)) {
|
|
6600
6706
|
process.env.ADA_PLUGIN_DIR = dir;
|
|
6601
6707
|
return;
|
|
6602
6708
|
}
|
|
@@ -6752,7 +6858,7 @@ function parseServerEndpoint(serverUrl) {
|
|
|
6752
6858
|
}
|
|
6753
6859
|
function commandAvailable(command) {
|
|
6754
6860
|
if (import_node_path14.default.isAbsolute(command)) {
|
|
6755
|
-
return (0,
|
|
6861
|
+
return (0, import_node_fs5.existsSync)(command);
|
|
6756
6862
|
}
|
|
6757
6863
|
const checker = process.platform === "win32" ? "where.exe" : "which";
|
|
6758
6864
|
const checked = (0, import_node_child_process5.spawnSync)(checker, [command], {
|
|
@@ -6796,7 +6902,7 @@ function resolveAppiumNodeEntrypoint() {
|
|
|
6796
6902
|
import_node_path14.default.join(process.cwd(), "..", "..", "node_modules", "appium", "build", "lib", "main.js")
|
|
6797
6903
|
];
|
|
6798
6904
|
for (const p of candidates) {
|
|
6799
|
-
if ((0,
|
|
6905
|
+
if ((0, import_node_fs5.existsSync)(p)) {
|
|
6800
6906
|
return p;
|
|
6801
6907
|
}
|
|
6802
6908
|
}
|
|
@@ -6815,11 +6921,11 @@ function loadPersistedHomes() {
|
|
|
6815
6921
|
import_node_path14.default.join(process.cwd(), "..", ".ada-agent", "deps-install-state.json")
|
|
6816
6922
|
];
|
|
6817
6923
|
for (const file of candidates) {
|
|
6818
|
-
if (!(0,
|
|
6924
|
+
if (!(0, import_node_fs5.existsSync)(file)) {
|
|
6819
6925
|
continue;
|
|
6820
6926
|
}
|
|
6821
6927
|
try {
|
|
6822
|
-
const raw = (0,
|
|
6928
|
+
const raw = (0, import_node_fs5.readFileSync)(file, "utf8");
|
|
6823
6929
|
const parsed = JSON.parse(raw);
|
|
6824
6930
|
const androidHome = typeof parsed.androidHome === "string" ? parsed.androidHome.trim() : "";
|
|
6825
6931
|
const appiumHome = typeof parsed.appiumHome === "string" ? parsed.appiumHome.trim() : "";
|
|
@@ -6852,11 +6958,11 @@ function resolveAndroidSdkRoot() {
|
|
|
6852
6958
|
process.env.USERPROFILE ? import_node_path14.default.join(process.env.USERPROFILE, "AppData", "Local", "Android", "Sdk") : null
|
|
6853
6959
|
].map((v) => typeof v === "string" ? v.trim() : "").filter(Boolean);
|
|
6854
6960
|
for (const sdkRoot of candidates) {
|
|
6855
|
-
if (persisted.androidHome && sdkRoot === persisted.androidHome && (0,
|
|
6961
|
+
if (persisted.androidHome && sdkRoot === persisted.androidHome && (0, import_node_fs5.existsSync)(sdkRoot)) {
|
|
6856
6962
|
return sdkRoot;
|
|
6857
6963
|
}
|
|
6858
6964
|
const platformTools = import_node_path14.default.join(sdkRoot, "platform-tools");
|
|
6859
|
-
if ((0,
|
|
6965
|
+
if ((0, import_node_fs5.existsSync)(platformTools)) {
|
|
6860
6966
|
return sdkRoot;
|
|
6861
6967
|
}
|
|
6862
6968
|
}
|
|
@@ -6867,11 +6973,11 @@ function getAppiumExtensionsFile(homeDir) {
|
|
|
6867
6973
|
}
|
|
6868
6974
|
function hasAppiumDriver(homeDir, driverName) {
|
|
6869
6975
|
const file = getAppiumExtensionsFile(homeDir);
|
|
6870
|
-
if (!(0,
|
|
6976
|
+
if (!(0, import_node_fs5.existsSync)(file)) {
|
|
6871
6977
|
return false;
|
|
6872
6978
|
}
|
|
6873
6979
|
try {
|
|
6874
|
-
const text = (0,
|
|
6980
|
+
const text = (0, import_node_fs5.readFileSync)(file, "utf8");
|
|
6875
6981
|
return text.toLowerCase().includes(driverName.toLowerCase());
|
|
6876
6982
|
} catch {
|
|
6877
6983
|
return false;
|
|
@@ -6894,7 +7000,7 @@ function resolveAppiumHome(platform) {
|
|
|
6894
7000
|
}
|
|
6895
7001
|
}
|
|
6896
7002
|
for (const candidate of uniq) {
|
|
6897
|
-
if ((0,
|
|
7003
|
+
if ((0, import_node_fs5.existsSync)(getAppiumExtensionsFile(candidate))) {
|
|
6898
7004
|
return candidate;
|
|
6899
7005
|
}
|
|
6900
7006
|
}
|
|
@@ -8358,7 +8464,7 @@ async function startMcpServer() {
|
|
|
8358
8464
|
mcpServers: {
|
|
8359
8465
|
"ada-mcp": {
|
|
8360
8466
|
command: "pnpm",
|
|
8361
|
-
args: ["dlx", "@ada-mcp/launcher@0.1.
|
|
8467
|
+
args: ["dlx", "@ada-mcp/launcher@0.1.3"]
|
|
8362
8468
|
}
|
|
8363
8469
|
}
|
|
8364
8470
|
};
|