@ada-mcp/mcp-server 0.1.19 → 0.1.20

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 CHANGED
@@ -3005,14 +3005,55 @@ async function resolveNativeDriversDir(workspaceRoot) {
3005
3005
  }
3006
3006
  return import_node_path4.default.join(root, DEFAULT_NATIVE_DRIVERS_DIR);
3007
3007
  }
3008
- function platformArchiveSuffix() {
3008
+ function geckodriverMirrorBase() {
3009
+ const fromEnv = process.env.ADA_GECKODRIVER_MIRROR?.trim();
3010
+ return (fromEnv || DEFAULT_GECKODRIVER_MIRROR).replace(/\/$/, "");
3011
+ }
3012
+ function geckodriverPlatformAsset(tag) {
3013
+ const t = tag.startsWith("v") ? tag : `v${tag}`;
3009
3014
  if (process.platform === "win32") {
3010
- return "win64.zip";
3015
+ const winSuffix = process.arch === "arm64" ? "win-aarch64" : process.arch === "ia32" ? "win32" : "win64";
3016
+ return { fileName: `geckodriver-${t}-${winSuffix}.zip`, archiveKind: "zip" };
3011
3017
  }
3012
3018
  if (process.platform === "darwin") {
3013
- return process.arch === "arm64" ? "macos-aarch64.zip" : "macos.zip";
3019
+ const macSuffix = process.arch === "arm64" ? "macos-aarch64" : "macos";
3020
+ return { fileName: `geckodriver-${t}-${macSuffix}.tar.gz`, archiveKind: "tar.gz" };
3021
+ }
3022
+ const linuxSuffix = process.arch === "arm64" ? "linux-aarch64" : process.arch === "ia32" ? "linux32" : "linux64";
3023
+ return { fileName: `geckodriver-${t}-${linuxSuffix}.tar.gz`, archiveKind: "tar.gz" };
3024
+ }
3025
+ function parseSemverTuple(version2) {
3026
+ const m = version2.replace(/^v/i, "").match(/^(\d+)\.(\d+)\.(\d+)/);
3027
+ if (!m) {
3028
+ return null;
3029
+ }
3030
+ return [Number(m[1]), Number(m[2]), Number(m[3])];
3031
+ }
3032
+ function compareSemverDesc(a, b) {
3033
+ const pa = parseSemverTuple(a);
3034
+ const pb = parseSemverTuple(b);
3035
+ if (!pa || !pb) {
3036
+ return 0;
3037
+ }
3038
+ for (let i = 0; i < 3; i += 1) {
3039
+ if (pa[i] !== pb[i]) {
3040
+ return pb[i] - pa[i];
3041
+ }
3014
3042
  }
3015
- return "linux64.zip";
3043
+ return 0;
3044
+ }
3045
+ async function fetchGeckodriverLatestFromMirror(mirrorBase) {
3046
+ const res = await fetch(`${mirrorBase}/`);
3047
+ if (!res.ok) {
3048
+ return null;
3049
+ }
3050
+ const html = await res.text();
3051
+ const tags = /* @__PURE__ */ new Set();
3052
+ for (const m of html.matchAll(/href="v(\d+\.\d+\.\d+)\//gi)) {
3053
+ tags.add(`v${m[1]}`);
3054
+ }
3055
+ const sorted = Array.from(tags).sort(compareSemverDesc);
3056
+ return sorted[0] ?? null;
3016
3057
  }
3017
3058
  function platformChromeLabel() {
3018
3059
  if (process.platform === "win32") {
@@ -3197,6 +3238,21 @@ async function extractZip(zipPath, destDir) {
3197
3238
  }
3198
3239
  await runCommand("unzip", ["-o", zipPath, "-d", destDir]);
3199
3240
  }
3241
+ async function extractTarGz(archivePath, destDir) {
3242
+ await import_promises4.default.mkdir(destDir, { recursive: true });
3243
+ if (process.platform === "win32") {
3244
+ await runCommand("tar", ["-xzf", archivePath, "-C", destDir]);
3245
+ return;
3246
+ }
3247
+ await runCommand("tar", ["-xzf", archivePath, "-C", destDir]);
3248
+ }
3249
+ async function extractDriverArchive(archivePath, destDir, kind) {
3250
+ if (kind === "zip") {
3251
+ await extractZip(archivePath, destDir);
3252
+ return;
3253
+ }
3254
+ await extractTarGz(archivePath, destDir);
3255
+ }
3200
3256
  async function findFileRecursive(dir, fileName) {
3201
3257
  const entries = await import_promises4.default.readdir(dir, { withFileTypes: true });
3202
3258
  for (const ent of entries) {
@@ -3224,13 +3280,26 @@ async function fetchGeckodriverReleaseVersion(requested) {
3224
3280
  if (requested && requested !== "latest") {
3225
3281
  return requested.startsWith("v") ? requested : `v${requested}`;
3226
3282
  }
3227
- const res = await fetch("https://api.github.com/repos/mozilla/geckodriver/releases/latest");
3228
- if (!res.ok) {
3229
- throw new Error(`Failed to fetch geckodriver latest release: HTTP ${res.status}`);
3283
+ const mirrorLatest = await fetchGeckodriverLatestFromMirror(geckodriverMirrorBase());
3284
+ if (mirrorLatest) {
3285
+ return mirrorLatest;
3230
3286
  }
3231
- const json3 = await res.json();
3232
- const tag = json3.tag_name ?? "v0.36.0";
3233
- return tag.startsWith("v") ? tag : `v${tag}`;
3287
+ try {
3288
+ const res = await fetch("https://api.github.com/repos/mozilla/geckodriver/releases/latest");
3289
+ if (res.ok) {
3290
+ const json3 = await res.json();
3291
+ const tag = json3.tag_name ?? "v0.36.0";
3292
+ return tag.startsWith("v") ? tag : `v${tag}`;
3293
+ }
3294
+ } catch {
3295
+ }
3296
+ return "v0.36.0";
3297
+ }
3298
+ function buildGeckodriverDownloadUrls(tag) {
3299
+ const { fileName, archiveKind } = geckodriverPlatformAsset(tag);
3300
+ const mirror = `${geckodriverMirrorBase()}/${tag}/${fileName}`;
3301
+ const github = `${GITHUB_GECKODRIVER_RELEASES}/download/${tag}/${fileName}`;
3302
+ return { mirror, github, fileName, archiveKind };
3234
3303
  }
3235
3304
  async function listChromedriverCfTVersions() {
3236
3305
  const res = await fetch(CHROME_FOR_TESTING_JSON);
@@ -3474,26 +3543,39 @@ async function downloadToFile(url2, destPath) {
3474
3543
  async function downloadGeckodriver(driversDir, versionInput, onLogLine) {
3475
3544
  const tag = await fetchGeckodriverReleaseVersion(versionInput);
3476
3545
  const version2 = tag.replace(/^v/, "");
3477
- const suffix = platformArchiveSuffix();
3478
- const assetName = `geckodriver-${tag}-${suffix}`.replace("vv", "v");
3479
- const url2 = `https://github.com/mozilla/geckodriver/releases/download/${tag}/geckodriver-${tag}-${suffix}`;
3546
+ const { mirror, github, fileName, archiveKind } = buildGeckodriverDownloadUrls(tag);
3480
3547
  await import_promises4.default.mkdir(driversDir, { recursive: true });
3481
- const zipPath = import_node_path4.default.join(driversDir, `_download_geckodriver_${version2}.zip`);
3548
+ const archiveExt = archiveKind === "zip" ? "zip" : "tar.gz";
3549
+ const archivePath = import_node_path4.default.join(driversDir, `_download_geckodriver_${version2}.${archiveExt}`);
3482
3550
  const extractDir = import_node_path4.default.join(driversDir, `_extract_geckodriver_${version2}`);
3483
- onLogLine?.(`[selenium] \u4E0B\u8F7D geckodriver ${tag} \u2192 ${driversDir}`);
3484
- onLogLine?.(`[selenium] URL: ${url2}`);
3485
- await downloadToFile(url2, zipPath);
3551
+ onLogLine?.(`[selenium] ?? geckodriver ${tag}?${fileName}?? ${driversDir}`);
3552
+ onLogLine?.(`[selenium] ??: ${mirror}`);
3553
+ let downloaded = false;
3554
+ try {
3555
+ await downloadToFile(mirror, archivePath);
3556
+ downloaded = true;
3557
+ } catch (mirrorError) {
3558
+ onLogLine?.(
3559
+ `[selenium][warn] ?????????: ${mirrorError instanceof Error ? mirrorError.message : String(mirrorError)}`
3560
+ );
3561
+ onLogLine?.(`[selenium] ?? GitHub: ${github}`);
3562
+ await downloadToFile(github, archivePath);
3563
+ downloaded = true;
3564
+ }
3565
+ if (!downloaded) {
3566
+ throw new Error(`geckodriver download failed for ${tag}`);
3567
+ }
3486
3568
  await import_promises4.default.rm(extractDir, { recursive: true, force: true });
3487
- await extractZip(zipPath, extractDir);
3569
+ await extractDriverArchive(archivePath, extractDir, archiveKind);
3488
3570
  const found = await findFileRecursive(extractDir, geckodriverExeName());
3489
3571
  if (!found) {
3490
- throw new Error(`geckodriver binary not found after extracting ${assetName}`);
3572
+ throw new Error(`geckodriver binary not found after extracting ${fileName}`);
3491
3573
  }
3492
3574
  const dest = import_node_path4.default.join(driversDir, geckodriverExeName());
3493
3575
  await copyExecutable(found, dest);
3494
- await import_promises4.default.rm(zipPath, { force: true });
3576
+ await import_promises4.default.rm(archivePath, { force: true });
3495
3577
  await import_promises4.default.rm(extractDir, { recursive: true, force: true });
3496
- onLogLine?.(`[selenium] geckodriver \u5DF2\u5199\u5165: ${dest}`);
3578
+ onLogLine?.(`[selenium] geckodriver ???: ${dest}`);
3497
3579
  return { path: dest, version: tag };
3498
3580
  }
3499
3581
  async function downloadChromedriver(driversDir, versionInput, onLogLine) {
@@ -3653,7 +3735,7 @@ async function ensureNativeWebDrivers(options = {}) {
3653
3735
  }
3654
3736
  return resolved;
3655
3737
  }
3656
- var import_node_child_process, import_promises4, import_node_path4, DEFAULT_NATIVE_DRIVERS_DIR, CHROME_FOR_TESTING_JSON;
3738
+ var import_node_child_process, import_promises4, import_node_path4, DEFAULT_NATIVE_DRIVERS_DIR, CHROME_FOR_TESTING_JSON, DEFAULT_GECKODRIVER_MIRROR, GITHUB_GECKODRIVER_RELEASES, SELENIUM_DRIVER_MANUAL_DOWNLOAD_REFERENCES;
3657
3739
  var init_src2 = __esm({
3658
3740
  "../../packages/native-drivers/src/index.ts"() {
3659
3741
  "use strict";
@@ -3662,6 +3744,46 @@ var init_src2 = __esm({
3662
3744
  import_node_path4 = __toESM(require("node:path"), 1);
3663
3745
  DEFAULT_NATIVE_DRIVERS_DIR = "dirver";
3664
3746
  CHROME_FOR_TESTING_JSON = "https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json";
3747
+ DEFAULT_GECKODRIVER_MIRROR = "https://mirrors.huaweicloud.com/geckodriver";
3748
+ GITHUB_GECKODRIVER_RELEASES = "https://github.com/mozilla/geckodriver/releases";
3749
+ SELENIUM_DRIVER_MANUAL_DOWNLOAD_REFERENCES = [
3750
+ {
3751
+ browser: "Chrome/Chromium",
3752
+ platforms: "Windows/Linux/macOS",
3753
+ vendor: "\u8C37\u6B4C",
3754
+ url: "https://chromedriver.storage.googleapis.com/index.html"
3755
+ },
3756
+ {
3757
+ browser: "Firefox",
3758
+ platforms: "Windows/Linux/macOS",
3759
+ vendor: "Mozilla / ?????",
3760
+ url: `${DEFAULT_GECKODRIVER_MIRROR}/v0.36.0/?????????????? ${GITHUB_GECKODRIVER_RELEASES}?`
3761
+ },
3762
+ {
3763
+ browser: "Edge",
3764
+ platforms: "win10",
3765
+ vendor: "\u5FAE\u8F6F",
3766
+ url: "https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/"
3767
+ },
3768
+ {
3769
+ browser: "Internet Explorer",
3770
+ platforms: "Windows",
3771
+ vendor: "Selenium \u9879\u76EE\u7EC4",
3772
+ url: "https://selenium-release.storage.googleapis.com/index.html"
3773
+ },
3774
+ {
3775
+ browser: "Safari",
3776
+ platforms: "macOS El Capitan \u53CA\u66F4\u9AD8\u7248\u672C",
3777
+ vendor: "\u82F9\u679C",
3778
+ url: "\uFF08\u7CFB\u7EDF\u5185\u7F6E\uFF0C\u65E0\u9700\u5355\u72EC\u4E0B\u8F7D\uFF09"
3779
+ },
3780
+ {
3781
+ browser: "Opera",
3782
+ platforms: "Windows/macOS/Linux",
3783
+ vendor: "Opera",
3784
+ url: "https://github.com/operasoftware/operachromiumdriver/releases"
3785
+ }
3786
+ ];
3665
3787
  }
3666
3788
  });
3667
3789
 
@@ -4128,6 +4250,32 @@ function appiumDriverPackageName(driver) {
4128
4250
  }
4129
4251
  return null;
4130
4252
  }
4253
+ function resolveAppiumDriverInstallTargets(driver, appiumMajor, compatibleSpecs) {
4254
+ const pkg = appiumDriverPackageName(driver);
4255
+ if (appiumMajor !== null && appiumMajor >= 3) {
4256
+ if (!APPIUM3_BUILTIN_DRIVER_NAMES.has(driver)) {
4257
+ const envHarmony = process.env.ADA_APPIUM_DRIVER_SPEC_HARMONYOS?.trim();
4258
+ if (driver === "harmonyos" && (envHarmony || pkg)) {
4259
+ return [envHarmony || pkg];
4260
+ }
4261
+ return pkg ? [pkg] : [driver];
4262
+ }
4263
+ const envOverride = driver === "uiautomator2" ? process.env.ADA_APPIUM_DRIVER_SPEC_UIAUTOMATOR2?.trim() : driver === "xcuitest" ? process.env.ADA_APPIUM_DRIVER_SPEC_XCUITEST?.trim() : "";
4264
+ if (envOverride) {
4265
+ return [envOverride, driver];
4266
+ }
4267
+ return [driver];
4268
+ }
4269
+ const baseTarget = pkg ?? driver;
4270
+ return compatibleSpecs.length > 0 ? compatibleSpecs : [baseTarget];
4271
+ }
4272
+ function buildAppiumDriverInstallArgs(target, appiumMajor) {
4273
+ const useNpmPackageSpec = appiumMajor === null || appiumMajor < 3 || target.includes("@") || target.startsWith("appium-") || target.includes("/");
4274
+ if (useNpmPackageSpec) {
4275
+ return ["exec", "appium", "driver", "install", "--source=npm", target];
4276
+ }
4277
+ return ["exec", "appium", "driver", "install", target];
4278
+ }
4131
4279
  async function getAppiumMajorVersion() {
4132
4280
  let version2 = "";
4133
4281
  try {
@@ -4553,13 +4701,14 @@ async function runAppiumDriverInstallWithPriority(config2, driver, onLogLine) {
4553
4701
  onLogLine?.(`[appium] \u5B89\u88C5\u9A71\u52A8: ${driver}`);
4554
4702
  const compatibleSpecs = await resolveCompatibleDriverSpecs(driver);
4555
4703
  const appiumMajor = await getAppiumMajorVersion();
4556
- const directPackage = appiumDriverPackageName(driver);
4557
- const baseTarget = directPackage ?? driver;
4558
- const targets = appiumMajor !== null && appiumMajor < 3 ? compatibleSpecs.length > 0 ? compatibleSpecs : [baseTarget] : [baseTarget, ...compatibleSpecs];
4559
- const uniqueTargets = Array.from(new Set(targets.filter(Boolean)));
4704
+ if (appiumMajor !== null && appiumMajor >= 3) {
4705
+ onLogLine?.(`[appium] \u68C0\u6D4B\u5230 Appium ${appiumMajor}.x\uFF0C\u4F7F\u7528\u5B98\u65B9\u9A71\u52A8\u540D\u5B89\u88C5\uFF08\u5982 uiautomator2\uFF09`);
4706
+ }
4707
+ const uniqueTargets = resolveAppiumDriverInstallTargets(driver, appiumMajor, compatibleSpecs);
4560
4708
  let lastError = void 0;
4561
4709
  for (const target of uniqueTargets) {
4562
- const installArgs = ["exec", "appium", "driver", "install", "--source=npm", target];
4710
+ const installArgs = buildAppiumDriverInstallArgs(target, appiumMajor);
4711
+ onLogLine?.(`[appium] \u6267\u884C: npm ${installArgs.join(" ")}`);
4563
4712
  const strategies = [
4564
4713
  {
4565
4714
  name: "npm",
@@ -5182,7 +5331,7 @@ async function getDependencyHealth(config2) {
5182
5331
  missingAppiumDrivers
5183
5332
  };
5184
5333
  }
5185
- var import_node_module, import_node_fs, import_node_child_process2, import_promises5, import_node_path5, require2, PINNED_PLAYWRIGHT_VERSION, PINNED_ZOD_VERSION, depsHumanLog, DEFAULT_NPM_REGISTRY_CANDIDATES, detectedBestRegistryByKey, PROGRESS_STEPS, PROGRESS_HUMAN_LABELS, DEFAULT_PLAYWRIGHT_HOST_CANDIDATES, CHINA_NPM_REGISTRY_HINTS, CHINA_PLAYWRIGHT_HOST_PRIORITY, PLAYWRIGHT_HOST_FALLBACK, PW_INSTALL_TARGETS;
5334
+ var import_node_module, import_node_fs, import_node_child_process2, import_promises5, import_node_path5, require2, PINNED_PLAYWRIGHT_VERSION, PINNED_ZOD_VERSION, depsHumanLog, DEFAULT_NPM_REGISTRY_CANDIDATES, APPIUM3_BUILTIN_DRIVER_NAMES, detectedBestRegistryByKey, PROGRESS_STEPS, PROGRESS_HUMAN_LABELS, DEFAULT_PLAYWRIGHT_HOST_CANDIDATES, CHINA_NPM_REGISTRY_HINTS, CHINA_PLAYWRIGHT_HOST_PRIORITY, PLAYWRIGHT_HOST_FALLBACK, PW_INSTALL_TARGETS;
5186
5335
  var init_dependency_installer = __esm({
5187
5336
  "../ada-agent/src/dependency-installer.ts"() {
5188
5337
  import_node_module = require("node:module");
@@ -5202,6 +5351,16 @@ var init_dependency_installer = __esm({
5202
5351
  "https://repo.huaweicloud.com/repository/npm",
5203
5352
  "https://registry.npmjs.org"
5204
5353
  ];
5354
+ APPIUM3_BUILTIN_DRIVER_NAMES = /* @__PURE__ */ new Set([
5355
+ "uiautomator2",
5356
+ "xcuitest",
5357
+ "espresso",
5358
+ "mac2",
5359
+ "windows",
5360
+ "safari",
5361
+ "gecko",
5362
+ "chromium"
5363
+ ]);
5205
5364
  detectedBestRegistryByKey = /* @__PURE__ */ new Map();
5206
5365
  PROGRESS_STEPS = [
5207
5366
  "deps.ensure.start",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ada-mcp/mcp-server",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "ADA MCP server for web/mobile automation (stdio + remote HTTP)",
5
5
  "private": false,
6
6
  "type": "commonjs",
@@ -232,6 +232,46 @@ var import_node_child_process = require("node:child_process");
232
232
  var import_promises = __toESM(require("node:fs/promises"), 1);
233
233
  var import_node_path = __toESM(require("node:path"), 1);
234
234
  var DEFAULT_NATIVE_DRIVERS_DIR = "dirver";
235
+ var DEFAULT_GECKODRIVER_MIRROR = "https://mirrors.huaweicloud.com/geckodriver";
236
+ var GITHUB_GECKODRIVER_RELEASES = "https://github.com/mozilla/geckodriver/releases";
237
+ var SELENIUM_DRIVER_MANUAL_DOWNLOAD_REFERENCES = [
238
+ {
239
+ browser: "Chrome/Chromium",
240
+ platforms: "Windows/Linux/macOS",
241
+ vendor: "\u8C37\u6B4C",
242
+ url: "https://chromedriver.storage.googleapis.com/index.html"
243
+ },
244
+ {
245
+ browser: "Firefox",
246
+ platforms: "Windows/Linux/macOS",
247
+ vendor: "Mozilla / ?????",
248
+ url: `${DEFAULT_GECKODRIVER_MIRROR}/v0.36.0/?????????????? ${GITHUB_GECKODRIVER_RELEASES}?`
249
+ },
250
+ {
251
+ browser: "Edge",
252
+ platforms: "win10",
253
+ vendor: "\u5FAE\u8F6F",
254
+ url: "https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/"
255
+ },
256
+ {
257
+ browser: "Internet Explorer",
258
+ platforms: "Windows",
259
+ vendor: "Selenium \u9879\u76EE\u7EC4",
260
+ url: "https://selenium-release.storage.googleapis.com/index.html"
261
+ },
262
+ {
263
+ browser: "Safari",
264
+ platforms: "macOS El Capitan \u53CA\u66F4\u9AD8\u7248\u672C",
265
+ vendor: "\u82F9\u679C",
266
+ url: "\uFF08\u7CFB\u7EDF\u5185\u7F6E\uFF0C\u65E0\u9700\u5355\u72EC\u4E0B\u8F7D\uFF09"
267
+ },
268
+ {
269
+ browser: "Opera",
270
+ platforms: "Windows/macOS/Linux",
271
+ vendor: "Opera",
272
+ url: "https://github.com/operasoftware/operachromiumdriver/releases"
273
+ }
274
+ ];
235
275
  async function fileExists(filePath) {
236
276
  try {
237
277
  await import_promises.default.access(filePath);