adspower-browser 2.0.2 → 2.0.3

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.
Files changed (3) hide show
  1. package/README.MD +38 -0
  2. package/cli/index.js +439 -198
  3. package/package.json +3 -2
package/README.MD CHANGED
@@ -61,6 +61,34 @@ ads start
61
61
  - `ads open-browser '{"profile_id":"abc123","launch_args":"..."}'`
62
62
  - Commands with no params: omit `<arg>` or use `'{}'`.
63
63
 
64
+ ## Shell Tab Completion
65
+
66
+ The CLI supports prefix tab completion for subcommands and common flags (`-k`, `-p`, etc.) via [`@bomb.sh/tab`](https://bomb.sh/docs/tab/). Enable it once in your shell:
67
+
68
+ **zsh**
69
+
70
+ ```bash
71
+ ads complete zsh > ~/.ads-completion.zsh
72
+ echo 'source ~/.ads-completion.zsh' >> ~/.zshrc
73
+ source ~/.ads-completion.zsh
74
+ ```
75
+
76
+ **bash**
77
+
78
+ ```bash
79
+ ads complete bash > ~/.ads-completion.bash
80
+ echo 'source ~/.ads-completion.bash' >> ~/.bashrc
81
+ source ~/.ads-completion.bash
82
+ ```
83
+
84
+ After setup, `ads`, `adspower`, and `adspower-browser` share the same completions:
85
+
86
+ ```bash
87
+ ads <Tab><Tab> # list subcommands
88
+ ads open-<Tab> # complete to open-browser
89
+ ads sta<Tab> # complete to start / status
90
+ ```
91
+
64
92
  ## Essential Commands With CLI
65
93
 
66
94
  You can use `ads -h` or `ads <command> -h` to view the specific parameters.
@@ -149,4 +177,14 @@ ads download-kernel '{"kernel_type":"Chrome","kernel_version":"..."}' # kernel
149
177
 
150
178
  ```bash
151
179
  ads update-patch '{"version_type":"stable"}' # version_type?:stable|beta
180
+ ```
181
+
182
+ ## Use CLI in Docker
183
+
184
+ copy the [`docker-compose.yml`](./docker-compose.yml)
185
+
186
+ ```bash
187
+ docker-compose -f ./docker-compose.yml up -d
188
+
189
+ docker-compose exec adspower-cli /bin/bash
152
190
  ```
package/cli/index.js CHANGED
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/index.ts
27
- var import_commander = require("commander");
27
+ var import_commander2 = require("commander");
28
28
 
29
29
  // src/store/index.ts
30
30
  var Store = class {
@@ -105,7 +105,8 @@ var util = __toESM(require("util"));
105
105
  var import_node_child_process = require("child_process");
106
106
  var import_colors = require("colors");
107
107
  var import_fs_extra2 = require("fs-extra2");
108
- var VERSION = "1.0.0";
108
+ var VERSION = (0, import_fs_extra2.readJsonSync)(path.join(__dirname, "../package.json")).version;
109
+ var VERSION_FILE = "1.0.0";
109
110
  var toTerminalLink = (url, label) => {
110
111
  const text = label || url;
111
112
  return `\x1B]8;;${url}\x07${text}\x1B]8;;\x07`;
@@ -158,7 +159,7 @@ var getPidFileDir = () => {
158
159
  return dir;
159
160
  };
160
161
  var pidFileName = () => {
161
- const md5 = crypto.createHash("md5").update(VERSION).digest("hex");
162
+ const md5 = crypto.createHash("md5").update(VERSION_FILE).digest("hex");
162
163
  return md5;
163
164
  };
164
165
  var writePidFile = (config2) => {
@@ -285,43 +286,6 @@ var initSqlite3 = () => {
285
286
  logSuccess(`[i] SQLite file initialized successfully!`);
286
287
  }
287
288
  };
288
- var renderKernelProgress = (result) => {
289
- const status = result.status || "pending";
290
- const progress = ["completed", "installing"].includes(status) ? 100 : Math.max(0, Math.min(100, Number(result.progress) || 0));
291
- if (!process.stdout.isTTY) {
292
- logInfo(`Kernel progress: ${progress}% [${status}]`);
293
- return;
294
- }
295
- const width = 30;
296
- const filled = Math.round(progress / 100 * width);
297
- const bar = `${"=".repeat(filled)}${"-".repeat(width - filled)}`;
298
- process.stdout.write(`\r[${bar}] ${progress.toFixed(0).padStart(3, " ")}% ${status} `);
299
- };
300
- var finishKernelProgress = () => {
301
- if (process.stdout.isTTY) {
302
- process.stdout.write("\n");
303
- }
304
- };
305
- var trackKernelDownload = async (fnc, args) => {
306
- while (true) {
307
- const result = await fnc(args);
308
- try {
309
- const resultJson = JSON.parse(result.replace("Kernel download/update status: ", ""));
310
- if (resultJson && resultJson.status && ["pending", "downloading", "completed", "installing", "failed"].includes(resultJson.status)) {
311
- renderKernelProgress(resultJson);
312
- if (["completed", "failed"].includes(resultJson.status)) {
313
- finishKernelProgress();
314
- return result;
315
- }
316
- await sleepTime(3e3);
317
- } else {
318
- return result;
319
- }
320
- } catch (error) {
321
- return result;
322
- }
323
- }
324
- };
325
289
 
326
290
  // src/core/start.ts
327
291
  var getEnv = () => {
@@ -547,9 +511,6 @@ var getChildStatus = async () => {
547
511
  }
548
512
  };
549
513
 
550
- // src/index.ts
551
- var import_colors2 = require("colors");
552
-
553
514
  // ../core/src/constants/api.ts
554
515
  var import_axios = __toESM(require("axios"));
555
516
 
@@ -1401,39 +1362,33 @@ var browserHandlers = {
1401
1362
  const requestBody = buildRequestBodyFor("open-browser", resolvedParams);
1402
1363
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.START_BROWSER}`, requestBody);
1403
1364
  if (response.data.code === 0) {
1404
- const autoNote = didAutoSetHeadless ? "\n\u5DF2\u6839\u636E\u8FD0\u884C\u73AF\u5883\u81EA\u52A8\u4F7F\u7528 headless=1\uFF08\u65E0\u53EF\u7528\u56FE\u5F62\u4F1A\u8BDD\uFF09\u3002\nAuto-set headless=1 (no graphical session detected)." : "";
1405
- return `Browser opened successfully with: ${Object.entries(response.data.data).map(([key, value]) => {
1406
- if (value && typeof value === "object") {
1407
- return Object.entries(value).map(([key2, value2]) => `ws.${key2}: ${value2}`).join("\n");
1408
- }
1409
- return `${key}: ${value}`;
1410
- }).join("\n")}${autoNote}`;
1365
+ return JSON.stringify(response.data.data, null, 2);
1411
1366
  }
1412
- throw new Error(`Failed to open browser: ${response.data.msg}`);
1367
+ throw new Error(response.data.msg);
1413
1368
  },
1414
1369
  async closeBrowser(params) {
1415
1370
  const requestBody = buildRequestBodyFor("close-browser", params);
1416
1371
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CLOSE_BROWSER}`, requestBody);
1417
1372
  if (response.data.code === 0) {
1418
- return "Browser closed successfully";
1373
+ return JSON.stringify(response.data.data, null, 2);
1419
1374
  }
1420
- throw new Error(`Failed to close browser: ${response.data.msg}`);
1375
+ throw new Error(response.data.msg);
1421
1376
  },
1422
1377
  async createBrowser(params) {
1423
1378
  const requestBody = buildRequestBodyFor("create-browser", params);
1424
1379
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CREATE_BROWSER}`, requestBody);
1425
1380
  if (response.data.code === 0) {
1426
- return `Browser created successfully with: ${Object.entries(response.data.data).map(([key, value]) => `${key}: ${value}`).join("\n")}`;
1381
+ return JSON.stringify(response.data.data, null, 2);
1427
1382
  }
1428
- throw new Error(`Failed to create browser: ${response.data.msg}`);
1383
+ throw new Error(response.data.msg);
1429
1384
  },
1430
1385
  async updateBrowser(params) {
1431
1386
  const requestBody = buildRequestBodyFor("update-browser", params);
1432
1387
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_BROWSER}`, requestBody);
1433
1388
  if (response.data.code === 0) {
1434
- return `Browser updated successfully with: ${Object.entries(response.data.data || {}).map(([key, value]) => `${key}: ${value}`).join("\n")}`;
1389
+ return JSON.stringify(response.data.data, null, 2);
1435
1390
  }
1436
- throw new Error(`Failed to update browser: ${response.data.msg}`);
1391
+ throw new Error(response.data.msg);
1437
1392
  },
1438
1393
  async deleteBrowser(params) {
1439
1394
  const response = await getApiClient().post(
@@ -1441,64 +1396,63 @@ var browserHandlers = {
1441
1396
  buildRequestBodyFor("delete-browser", params)
1442
1397
  );
1443
1398
  if (response.data.code === 0) {
1444
- return `Browsers deleted successfully: ${params.profile_id.join(", ")}`;
1399
+ return JSON.stringify(response.data.data, null, 2);
1445
1400
  }
1446
- throw new Error(`Failed to delete browsers: ${response.data.msg}`);
1401
+ throw new Error(response.data.msg);
1447
1402
  },
1448
1403
  async getBrowserList(params) {
1449
1404
  const requestBody = buildRequestBodyFor("get-browser-list", params);
1450
1405
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_BROWSER_LIST}`, requestBody);
1451
1406
  if (response.data.code === 0) {
1452
- return `Browser list: ${JSON.stringify(response.data.data.list, null, 2)}`;
1407
+ return JSON.stringify(response.data.data, null, 2);
1453
1408
  }
1454
- throw new Error(`Failed to get browser list: ${response.data.msg}`);
1409
+ throw new Error(response.data.msg);
1455
1410
  },
1456
1411
  async getOpenedBrowser() {
1457
1412
  const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_OPENED_BROWSER}`);
1458
1413
  if (response.data.code === 0) {
1459
- return `Opened browser list: ${JSON.stringify(response.data.data.list, null, 2)}`;
1414
+ return JSON.stringify(response.data.data, null, 2);
1460
1415
  }
1461
- throw new Error(`Failed to get opened browsers: ${response.data.msg}`);
1416
+ throw new Error(response.data.msg);
1462
1417
  },
1463
1418
  async moveBrowser(params) {
1464
1419
  const requestBody = buildRequestBodyFor("move-browser", params);
1465
1420
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.MOVE_BROWSER}`, requestBody);
1466
- const { group_id, user_ids } = params;
1467
1421
  if (response.data.code === 0) {
1468
- return `Browsers moved successfully to group ${group_id}: ${user_ids.join(", ")}`;
1422
+ return JSON.stringify(response.data.data, null, 2);
1469
1423
  }
1470
- throw new Error(`Failed to move browsers: ${response.data.msg}`);
1424
+ throw new Error(response.data.msg);
1471
1425
  },
1472
1426
  async getProfileCookies(params) {
1473
1427
  const query = buildQueryParamsFor("get-profile-cookies", params);
1474
1428
  const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_PROFILE_COOKIES}`, { params: query });
1475
1429
  if (response.data.code === 0) {
1476
- return `Profile cookies: ${JSON.stringify(response.data.data, null, 2)}`;
1430
+ return JSON.stringify(response.data.data, null, 2);
1477
1431
  }
1478
- throw new Error(`Failed to get profile cookies: ${response.data.msg}`);
1432
+ throw new Error(response.data.msg);
1479
1433
  },
1480
1434
  async getProfileUa(params) {
1481
1435
  const requestBody = buildRequestBodyFor("get-profile-ua", params);
1482
1436
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_PROFILE_UA}`, requestBody);
1483
1437
  if (response.data.code === 0) {
1484
- return `Profile User-Agent: ${JSON.stringify(response.data.data, null, 2)}`;
1438
+ return JSON.stringify(response.data.data, null, 2);
1485
1439
  }
1486
- throw new Error(`Failed to get profile User-Agent: ${response.data.msg}`);
1440
+ throw new Error(response.data.msg);
1487
1441
  },
1488
1442
  async closeAllProfiles(_params) {
1489
1443
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CLOSE_ALL_PROFILES}`, {});
1490
- if (response.data.code === 0) {
1491
- return "All profiles closed successfully";
1444
+ if (response.data.data.code === 0) {
1445
+ return JSON.stringify(response.data.data, null, 2);
1492
1446
  }
1493
- throw new Error(`Failed to close all profiles: ${response.data.msg}`);
1447
+ throw new Error(response.data.data.msg);
1494
1448
  },
1495
1449
  async newFingerprint(params) {
1496
1450
  const requestBody = buildRequestBodyFor("new-fingerprint", params);
1497
1451
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.NEW_FINGERPRINT}`, requestBody);
1498
1452
  if (response.data.code === 0) {
1499
- return `New fingerprint created: ${JSON.stringify(response.data.data, null, 2)}`;
1453
+ return JSON.stringify(response.data.data, null, 2);
1500
1454
  }
1501
- throw new Error(`Failed to create new fingerprint: ${response.data.msg}`);
1455
+ throw new Error(response.data.msg);
1502
1456
  },
1503
1457
  async deleteCacheV2(params) {
1504
1458
  const response = await getApiClient().post(
@@ -1506,33 +1460,33 @@ var browserHandlers = {
1506
1460
  buildRequestBodyFor("delete-cache-v2", params)
1507
1461
  );
1508
1462
  if (response.data.code === 0) {
1509
- return `Cache deleted successfully for profiles: ${params.profile_id.join(", ")}`;
1463
+ return JSON.stringify(response.data.data, null, 2);
1510
1464
  }
1511
- throw new Error(`Failed to delete cache: ${response.data.msg}`);
1465
+ throw new Error(response.data.msg);
1512
1466
  },
1513
1467
  async shareProfile(params) {
1514
1468
  const requestBody = buildRequestBodyFor("share-profile", params);
1515
1469
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.SHARE_PROFILE}`, requestBody);
1516
1470
  if (response.data.code === 0) {
1517
- return `Profiles shared successfully: ${params.profile_id.join(", ")}`;
1471
+ return JSON.stringify(response.data.data, null, 2);
1518
1472
  }
1519
- throw new Error(`Failed to share profiles: ${response.data.msg}`);
1473
+ throw new Error(response.data.msg);
1520
1474
  },
1521
1475
  async getBrowserActive(params) {
1522
1476
  const query = buildQueryParamsFor("get-browser-active", params);
1523
1477
  const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_BROWSER_ACTIVE}`, { params: query });
1524
1478
  if (response.data.code === 0) {
1525
- return `Browser active info: ${JSON.stringify(response.data.data, null, 2)}`;
1479
+ return JSON.stringify(response.data.data, null, 2);
1526
1480
  }
1527
- throw new Error(`Failed to get browser active: ${response.data.msg}`);
1481
+ throw new Error(response.data.msg);
1528
1482
  },
1529
1483
  async getCloudActive(params) {
1530
1484
  const requestBody = buildRequestBodyFor("get-cloud-active", params);
1531
1485
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_CLOUD_ACTIVE}`, requestBody);
1532
1486
  if (response.data.code === 0) {
1533
- return `Cloud active browsers: ${JSON.stringify(response.data.data, null, 2)}`;
1487
+ return JSON.stringify(response.data.data, null, 2);
1534
1488
  }
1535
- throw new Error(`Failed to get cloud active browsers: ${response.data.msg}`);
1489
+ throw new Error(response.data.msg);
1536
1490
  }
1537
1491
  };
1538
1492
 
@@ -1541,28 +1495,26 @@ var groupHandlers = {
1541
1495
  async createGroup(params) {
1542
1496
  const requestBody = buildRequestBodyFor("create-group", params);
1543
1497
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CREATE_GROUP}`, requestBody);
1544
- const { group_name, remark } = params;
1545
1498
  if (response.data.code === 0) {
1546
- return `Group created successfully with name: ${group_name}${remark ? `, remark: ${remark}` : ""}`;
1499
+ return JSON.stringify(response.data.data, null, 2);
1547
1500
  }
1548
- throw new Error(`Failed to create group: ${response.data.msg}`);
1501
+ throw new Error(response.data.msg);
1549
1502
  },
1550
1503
  async updateGroup(params) {
1551
1504
  const requestBody = buildRequestBodyFor("update-group", params);
1552
1505
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_GROUP}`, requestBody);
1553
- const { group_id, group_name, remark } = params;
1554
1506
  if (response.data.code === 0) {
1555
- return `Group updated successfully with id: ${group_id}, name: ${group_name}${remark !== void 0 ? `, remark: ${remark === null ? "(cleared)" : remark}` : ""}`;
1507
+ return JSON.stringify(response.data.data, null, 2);
1556
1508
  }
1557
- throw new Error(`Failed to update group: ${response.data.msg}`);
1509
+ throw new Error(response.data.msg);
1558
1510
  },
1559
1511
  async getGroupList(params) {
1560
1512
  const query = buildQueryParamsFor("get-group-list", params);
1561
1513
  const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_GROUP_LIST}`, { params: query });
1562
1514
  if (response.data.code === 0) {
1563
- return `Group list: ${JSON.stringify(response.data.data.list, null, 2)}`;
1515
+ return JSON.stringify(response.data.data, null, 2);
1564
1516
  }
1565
- throw new Error(`Failed to get group list: ${response.data.msg}`);
1517
+ throw new Error(response.data.msg);
1566
1518
  }
1567
1519
  };
1568
1520
 
@@ -1570,12 +1522,12 @@ var groupHandlers = {
1570
1522
  var applicationHandlers = {
1571
1523
  async checkStatus() {
1572
1524
  const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.STATUS}`);
1573
- return `Connection status: ${JSON.stringify(response.data, null, 2)}`;
1525
+ return JSON.stringify(response.data, null, 2);
1574
1526
  },
1575
1527
  async getApplicationList(params) {
1576
1528
  const query = buildQueryParamsFor("get-application-list", params);
1577
1529
  const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_APPLICATION_LIST}`, { params: query });
1578
- return `Application list: ${JSON.stringify(response.data.data.list, null, 2)}`;
1530
+ return JSON.stringify(response.data.data, null, 2);
1579
1531
  }
1580
1532
  };
1581
1533
 
@@ -1607,25 +1559,25 @@ var proxyHandlers = {
1607
1559
  const requestBody = params.map((proxy) => buildCreateProxyRequestBody(proxy));
1608
1560
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CREATE_PROXY}`, requestBody);
1609
1561
  if (response.data.code === 0) {
1610
- return `Proxy created successfully with: ${Object.entries(response.data.data || {}).map(([key, value]) => `${key}: ${value}`).join("\n")}`;
1562
+ return JSON.stringify(response.data.data, null, 2);
1611
1563
  }
1612
- throw new Error(`Failed to create proxy: ${response.data.msg}`);
1564
+ throw new Error(response.data.msg);
1613
1565
  },
1614
1566
  async updateProxy(params) {
1615
1567
  const requestBody = buildRequestBodyFor("update-proxy", params);
1616
1568
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_PROXY}`, requestBody);
1617
1569
  if (response.data.code === 0) {
1618
- return `Proxy updated successfully with: ${Object.entries(response.data.data || {}).map(([key, value]) => `${key}: ${value}`).join("\n")}`;
1570
+ return JSON.stringify(response.data.data, null, 2);
1619
1571
  }
1620
- throw new Error(`Failed to update proxy: ${response.data.msg}`);
1572
+ throw new Error(response.data.msg);
1621
1573
  },
1622
1574
  async getProxyList(params) {
1623
1575
  const requestBody = buildRequestBodyFor("get-proxy-list", params);
1624
1576
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_PROXY_LIST}`, requestBody);
1625
1577
  if (response.data.code === 0) {
1626
- return `Proxy list: ${JSON.stringify(response.data.data.list || response.data.data, null, 2)}`;
1578
+ return JSON.stringify(response.data.data, null, 2);
1627
1579
  }
1628
- throw new Error(`Failed to get proxy list: ${response.data.msg}`);
1580
+ throw new Error(response.data.msg);
1629
1581
  },
1630
1582
  async deleteProxy(params) {
1631
1583
  const response = await getApiClient().post(
@@ -1634,9 +1586,9 @@ var proxyHandlers = {
1634
1586
  );
1635
1587
  const { proxy_id } = params;
1636
1588
  if (response.data.code === 0) {
1637
- return `Proxies deleted successfully: ${proxy_id.join(", ")}`;
1589
+ return JSON.stringify(response.data.data, null, 2);
1638
1590
  }
1639
- throw new Error(`Failed to delete proxies: ${response.data.msg}`);
1591
+ throw new Error(response.data.msg);
1640
1592
  }
1641
1593
  };
1642
1594
 
@@ -1656,30 +1608,30 @@ var tagHandlers = {
1656
1608
  }
1657
1609
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_TAG_LIST}`, requestBody);
1658
1610
  if (response.data.code === 0) {
1659
- return `Tag list: ${JSON.stringify(response.data.data.list || response.data.data, null, 2)}`;
1611
+ return JSON.stringify(response.data.data, null, 2);
1660
1612
  }
1661
- throw new Error(`Failed to get tag list: ${response.data.msg}`);
1613
+ throw new Error(response.data.msg);
1662
1614
  },
1663
1615
  async createTag({ tags }) {
1664
1616
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CREATE_TAG}`, { tags });
1665
1617
  if (response.data.code === 0) {
1666
- return `Tags created successfully: ${JSON.stringify(response.data.data, null, 2)}`;
1618
+ return JSON.stringify(response.data.data, null, 2);
1667
1619
  }
1668
- throw new Error(`Failed to create tags: ${response.data.msg}`);
1620
+ throw new Error(response.data.msg);
1669
1621
  },
1670
1622
  async updateTag({ tags }) {
1671
1623
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_TAG}`, { tags });
1672
1624
  if (response.data.code === 0) {
1673
- return `Tags updated successfully: ${JSON.stringify(response.data.data, null, 2)}`;
1625
+ return JSON.stringify(response.data.data, null, 2);
1674
1626
  }
1675
- throw new Error(`Failed to update tags: ${response.data.msg}`);
1627
+ throw new Error(response.data.msg);
1676
1628
  },
1677
1629
  async deleteTag({ ids }) {
1678
1630
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.DELETE_TAG}`, { ids });
1679
1631
  if (response.data.code === 0) {
1680
- return `Tags deleted successfully: ${ids.join(", ")}`;
1632
+ return JSON.stringify(response.data.data, null, 2);
1681
1633
  }
1682
- throw new Error(`Failed to delete tags: ${response.data.msg}`);
1634
+ throw new Error(response.data.msg);
1683
1635
  }
1684
1636
  };
1685
1637
 
@@ -1748,9 +1700,9 @@ var kernelHandlers = {
1748
1700
  kernel_version
1749
1701
  });
1750
1702
  if (response.data.code === 0) {
1751
- return `Kernel download/update status: ${JSON.stringify(response.data.data, null, 2)}`;
1703
+ return JSON.stringify(response.data.data, null, 2);
1752
1704
  }
1753
- throw new Error(`Failed to download/update kernel: ${response.data.msg}`);
1705
+ throw new Error(response.data.msg);
1754
1706
  },
1755
1707
  async getKernelList({ kernel_type }) {
1756
1708
  const params = new URLSearchParams();
@@ -1759,9 +1711,9 @@ var kernelHandlers = {
1759
1711
  }
1760
1712
  const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_KERNEL_LIST}`, { params });
1761
1713
  if (response.data.code === 0) {
1762
- return `Kernel list: ${JSON.stringify(response.data.data.list || response.data.data, null, 2)}`;
1714
+ return JSON.stringify(response.data.data, null, 2);
1763
1715
  }
1764
- throw new Error(`Failed to get kernel list: ${response.data.msg}`);
1716
+ throw new Error(response.data.msg);
1765
1717
  }
1766
1718
  };
1767
1719
 
@@ -1774,9 +1726,9 @@ var patchHandlers = {
1774
1726
  }
1775
1727
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_PATCH}`, requestBody);
1776
1728
  if (response.data.code === 0) {
1777
- return `Patch update status: ${JSON.stringify(response.data.data, null, 2)}, message: ${response.data.msg}`;
1729
+ return JSON.stringify(response.data.data, null, 2);
1778
1730
  }
1779
- throw new Error(`Failed to update patch: ${response.data.msg}`);
1731
+ throw new Error(response.data.msg);
1780
1732
  }
1781
1733
  };
1782
1734
 
@@ -2537,167 +2489,258 @@ var schemas = {
2537
2489
  };
2538
2490
 
2539
2491
  // src/cli.ts
2492
+ function formatJsonValueForHelp(value, indent) {
2493
+ const pad = " ".repeat(indent);
2494
+ const childPad = " ".repeat(indent + 1);
2495
+ if (value === null || typeof value !== "object") {
2496
+ return JSON.stringify(value);
2497
+ }
2498
+ if (Array.isArray(value)) {
2499
+ if (value.length === 0) {
2500
+ return "[]";
2501
+ }
2502
+ const lines2 = value.map((item) => `${childPad}${formatJsonValueForHelp(item, indent + 1)}`);
2503
+ return `[
2504
+ ${lines2.join(",\n")}
2505
+ ${pad}]`;
2506
+ }
2507
+ const entries = Object.entries(value);
2508
+ if (entries.length === 0) {
2509
+ return "{}";
2510
+ }
2511
+ const lines = entries.map(([key, val]) => {
2512
+ if (["enum", "oneOf", "required"].includes(key) && Array.isArray(val)) {
2513
+ return `${childPad}${JSON.stringify(key)}: ${JSON.stringify(val)}`;
2514
+ }
2515
+ return `${childPad}${JSON.stringify(key)}: ${formatJsonValueForHelp(val, indent + 1)}`;
2516
+ });
2517
+ return `{
2518
+ ${lines.join(",\n")}
2519
+ ${pad}}`;
2520
+ }
2521
+ function formatSchemaPropertiesForHelp(properties) {
2522
+ return formatJsonValueForHelp(properties, 0);
2523
+ }
2524
+ function schemaParamsDescription(schema, type) {
2525
+ let paramStr = "view help: https://documenter.getpostman.com/view/45822952/2sB2x5JDXn\n";
2526
+ switch (type) {
2527
+ case "open-browser":
2528
+ paramStr += `use cmd: "ads open-browser <profile_id>"
2529
+ or use params: "ads open-browser '{"profile_id":"..."}' "
2530
+ `;
2531
+ break;
2532
+ case "close-browser":
2533
+ paramStr += `use cmd: "ads close-browser <profile_id>"
2534
+ or use params: "ads close-browser '{"profile_id":"..."}' "
2535
+ `;
2536
+ break;
2537
+ case "get-profile-cookies":
2538
+ paramStr += `use cmd: "ads get-profile-cookies <profile_id>"
2539
+ or use params: "ads get-profile-cookies '{"profile_id":"..."}' "
2540
+ `;
2541
+ break;
2542
+ case "get-browser-active":
2543
+ paramStr += `use cmd: "ads get-browser-active <profile_id>"
2544
+ or use params: "ads get-browser-active '{"profile_id":"..."}' "
2545
+ `;
2546
+ break;
2547
+ }
2548
+ const _str = formatSchemaPropertiesForHelp(schema.toJSONSchema().properties);
2549
+ return paramStr + _str;
2550
+ }
2540
2551
  var STATELESS_HANDLERS = {
2541
2552
  "open-browser": {
2542
2553
  fn: browserHandlers.openBrowser,
2543
2554
  description: buildCliCommandDescription(
2544
2555
  "open-browser",
2545
2556
  "Open the browser, both environment and profile mean browser"
2546
- )
2557
+ ),
2558
+ paramsDescription: schemaParamsDescription(schemas.openBrowserSchema, "open-browser")
2547
2559
  },
2548
2560
  "close-browser": {
2549
2561
  fn: browserHandlers.closeBrowser,
2550
- description: buildCliCommandDescription("close-browser", "Close the browser")
2562
+ description: buildCliCommandDescription("close-browser", "Close the browser"),
2563
+ paramsDescription: schemaParamsDescription(schemas.closeBrowserSchema, "close-browser")
2551
2564
  },
2552
2565
  "create-browser": {
2553
2566
  fn: browserHandlers.createBrowser,
2554
- description: buildCliCommandDescription("create-browser", "Create a browser")
2567
+ description: buildCliCommandDescription("create-browser", "Create a browser"),
2568
+ paramsDescription: schemaParamsDescription(schemas.createBrowserSchema, "create-browser")
2555
2569
  },
2556
2570
  "update-browser": {
2557
2571
  fn: browserHandlers.updateBrowser,
2558
- description: buildCliCommandDescription("update-browser", "Update the browser")
2572
+ description: buildCliCommandDescription("update-browser", "Update the browser"),
2573
+ paramsDescription: schemaParamsDescription(schemas.updateBrowserSchema, "update-browser")
2559
2574
  },
2560
2575
  "delete-browser": {
2561
2576
  fn: browserHandlers.deleteBrowser,
2562
- description: buildCliCommandDescription("delete-browser", "Delete the browser")
2577
+ description: buildCliCommandDescription("delete-browser", "Delete the browser"),
2578
+ paramsDescription: schemaParamsDescription(schemas.deleteBrowserSchema, "delete-browser")
2563
2579
  },
2564
2580
  "get-browser-list": {
2565
2581
  fn: browserHandlers.getBrowserList,
2566
- description: buildCliCommandDescription("get-browser-list", "Get the list of browsers")
2582
+ description: buildCliCommandDescription("get-browser-list", "Get the list of browsers"),
2583
+ paramsDescription: schemaParamsDescription(schemas.getBrowserListSchema, "get-browser-list")
2567
2584
  },
2568
2585
  "get-opened-browser": {
2569
2586
  fn: browserHandlers.getOpenedBrowser,
2570
- description: buildCliCommandDescription("get-opened-browser", "Get the list of opened browsers")
2587
+ description: buildCliCommandDescription("get-opened-browser", "Get the list of opened browsers"),
2588
+ paramsDescription: schemaParamsDescription(schemas.emptySchema, "get-opened-browser")
2571
2589
  },
2572
2590
  "move-browser": {
2573
2591
  fn: browserHandlers.moveBrowser,
2574
- description: buildCliCommandDescription("move-browser", "Move browsers to a group")
2592
+ description: buildCliCommandDescription("move-browser", "Move browsers to a group"),
2593
+ paramsDescription: schemaParamsDescription(schemas.moveBrowserSchema, "move-browser")
2575
2594
  },
2576
2595
  "get-profile-cookies": {
2577
2596
  fn: browserHandlers.getProfileCookies,
2578
2597
  description: buildCliCommandDescription(
2579
2598
  "get-profile-cookies",
2580
2599
  "Query and return cookies of the specified profile. Only one profile can be queried per request."
2581
- )
2600
+ ),
2601
+ paramsDescription: schemaParamsDescription(schemas.getProfileCookiesSchema, "get-profile-cookies")
2582
2602
  },
2583
2603
  "get-profile-ua": {
2584
2604
  fn: browserHandlers.getProfileUa,
2585
2605
  description: buildCliCommandDescription(
2586
2606
  "get-profile-ua",
2587
2607
  "Query and return the User-Agent of specified profiles. Up to 10 profiles can be queried per request."
2588
- )
2608
+ ),
2609
+ paramsDescription: schemaParamsDescription(schemas.getProfileUaSchema, "get-profile-ua")
2589
2610
  },
2590
2611
  "close-all-profiles": {
2591
2612
  fn: browserHandlers.closeAllProfiles,
2592
2613
  description: buildCliCommandDescription(
2593
2614
  "close-all-profiles",
2594
2615
  "Close all opened profiles on the current device"
2595
- )
2616
+ ),
2617
+ paramsDescription: schemaParamsDescription(schemas.closeAllProfilesSchema, "close-all-profiles")
2596
2618
  },
2597
2619
  "new-fingerprint": {
2598
2620
  fn: browserHandlers.newFingerprint,
2599
2621
  description: buildCliCommandDescription(
2600
2622
  "new-fingerprint",
2601
2623
  "Generate a new fingerprint for specified profiles. Up to 10 profiles are supported per request."
2602
- )
2624
+ ),
2625
+ paramsDescription: schemaParamsDescription(schemas.newFingerprintSchema, "new-fingerprint")
2603
2626
  },
2604
2627
  "delete-cache-v2": {
2605
2628
  fn: browserHandlers.deleteCacheV2,
2606
2629
  description: buildCliCommandDescription(
2607
2630
  "delete-cache-v2",
2608
2631
  "Clear local cache of specific profiles.For account security, please ensure that there are no open browsers on the device when using this interface."
2609
- )
2632
+ ),
2633
+ paramsDescription: schemaParamsDescription(schemas.deleteCacheV2Schema, "delete-cache-v2")
2610
2634
  },
2611
2635
  "share-profile": {
2612
2636
  fn: browserHandlers.shareProfile,
2613
2637
  description: buildCliCommandDescription(
2614
2638
  "share-profile",
2615
2639
  "Share profiles via account email or phone number. The maximum number of profiles that can be shared at one time is 200."
2616
- )
2640
+ ),
2641
+ paramsDescription: schemaParamsDescription(schemas.shareProfileSchema, "share-profile")
2617
2642
  },
2618
2643
  "get-browser-active": {
2619
2644
  fn: browserHandlers.getBrowserActive,
2620
- description: buildCliCommandDescription("get-browser-active", "Get active browser profile information")
2645
+ description: buildCliCommandDescription("get-browser-active", "Get active browser profile information"),
2646
+ paramsDescription: schemaParamsDescription(schemas.getBrowserActiveSchema, "get-browser-active")
2621
2647
  },
2622
2648
  "get-cloud-active": {
2623
2649
  fn: browserHandlers.getCloudActive,
2624
2650
  description: buildCliCommandDescription(
2625
2651
  "get-cloud-active",
2626
2652
  'Query the status of browser profiles by user_ids, up to 100 profiles per request. If the team has enabled "Multi device mode," specific statuses cannot be retrieved and the response will indicate "Profile not opened."'
2627
- )
2653
+ ),
2654
+ paramsDescription: schemaParamsDescription(schemas.getCloudActiveSchema, "get-cloud-active")
2628
2655
  },
2629
2656
  "create-group": {
2630
2657
  fn: groupHandlers.createGroup,
2631
- description: buildCliCommandDescription("create-group", "Create a browser group")
2658
+ description: buildCliCommandDescription("create-group", "Create a browser group"),
2659
+ paramsDescription: schemaParamsDescription(schemas.createGroupSchema, "create-group")
2632
2660
  },
2633
2661
  "update-group": {
2634
2662
  fn: groupHandlers.updateGroup,
2635
- description: buildCliCommandDescription("update-group", "Update the browser group")
2663
+ description: buildCliCommandDescription("update-group", "Update the browser group"),
2664
+ paramsDescription: schemaParamsDescription(schemas.updateGroupSchema, "update-group")
2636
2665
  },
2637
2666
  "get-group-list": {
2638
2667
  fn: groupHandlers.getGroupList,
2639
- description: buildCliCommandDescription("get-group-list", "Get the list of groups")
2668
+ description: buildCliCommandDescription("get-group-list", "Get the list of groups"),
2669
+ paramsDescription: schemaParamsDescription(schemas.getGroupListSchema, "get-group-list")
2640
2670
  },
2641
2671
  "check-status": {
2642
2672
  fn: applicationHandlers.checkStatus,
2643
2673
  description: buildCliCommandDescription(
2644
2674
  "check-status",
2645
2675
  "Check the availability of the current device API interface (Connection Status)"
2646
- )
2676
+ ),
2677
+ paramsDescription: schemaParamsDescription(schemas.emptySchema, "check-status")
2647
2678
  },
2648
2679
  "get-application-list": {
2649
2680
  fn: applicationHandlers.getApplicationList,
2650
2681
  description: buildCliCommandDescription(
2651
2682
  "get-application-list",
2652
2683
  "Get the list of applications (categories)"
2653
- )
2684
+ ),
2685
+ paramsDescription: schemaParamsDescription(schemas.getApplicationListSchema, "get-application-list")
2654
2686
  },
2655
2687
  "create-proxy": {
2656
2688
  fn: proxyHandlers.createProxy,
2657
- description: buildCliCommandDescription("create-proxy", "Create the proxy")
2689
+ description: buildCliCommandDescription("create-proxy", "Create the proxy"),
2690
+ paramsDescription: schemaParamsDescription(schemas.createProxySchema, "create-proxy")
2658
2691
  },
2659
2692
  "update-proxy": {
2660
2693
  fn: proxyHandlers.updateProxy,
2661
- description: buildCliCommandDescription("update-proxy", "Update the proxy")
2694
+ description: buildCliCommandDescription("update-proxy", "Update the proxy"),
2695
+ paramsDescription: schemaParamsDescription(schemas.updateProxySchema, "update-proxy")
2662
2696
  },
2663
2697
  "get-proxy-list": {
2664
2698
  fn: proxyHandlers.getProxyList,
2665
- description: buildCliCommandDescription("get-proxy-list", "Get the list of proxies")
2699
+ description: buildCliCommandDescription("get-proxy-list", "Get the list of proxies"),
2700
+ paramsDescription: schemaParamsDescription(schemas.getProxyListSchema, "get-proxy-list")
2666
2701
  },
2667
2702
  "delete-proxy": {
2668
2703
  fn: proxyHandlers.deleteProxy,
2669
- description: buildCliCommandDescription("delete-proxy", "Delete the proxy")
2704
+ description: buildCliCommandDescription("delete-proxy", "Delete the proxy"),
2705
+ paramsDescription: schemaParamsDescription(schemas.deleteProxySchema, "delete-proxy")
2670
2706
  },
2671
2707
  "get-tag-list": {
2672
2708
  fn: tagHandlers.getTagList,
2673
- description: buildCliCommandDescription("get-tag-list", "Get the list of browser tags")
2709
+ description: buildCliCommandDescription("get-tag-list", "Get the list of browser tags"),
2710
+ paramsDescription: schemaParamsDescription(schemas.getTagListSchema, "get-tag-list")
2674
2711
  },
2675
2712
  "create-tag": {
2676
2713
  fn: tagHandlers.createTag,
2677
- description: buildCliCommandDescription("create-tag", "Create browser tags (batch supported)")
2714
+ description: buildCliCommandDescription("create-tag", "Create browser tags (batch supported)"),
2715
+ paramsDescription: schemaParamsDescription(schemas.createTagSchema, "create-tag")
2678
2716
  },
2679
2717
  "update-tag": {
2680
2718
  fn: tagHandlers.updateTag,
2681
- description: buildCliCommandDescription("update-tag", "Update browser tags (batch supported)")
2719
+ description: buildCliCommandDescription("update-tag", "Update browser tags (batch supported)"),
2720
+ paramsDescription: schemaParamsDescription(schemas.updateTagSchema, "update-tag")
2682
2721
  },
2683
2722
  "delete-tag": {
2684
2723
  fn: tagHandlers.deleteTag,
2685
- description: buildCliCommandDescription("delete-tag", "Delete browser tags")
2724
+ description: buildCliCommandDescription("delete-tag", "Delete browser tags"),
2725
+ paramsDescription: schemaParamsDescription(schemas.deleteTagSchema, "delete-tag")
2686
2726
  },
2687
2727
  "download-kernel": {
2688
2728
  fn: kernelHandlers.downloadKernel,
2689
2729
  description: buildCliCommandDescription(
2690
2730
  "download-kernel",
2691
2731
  "Download or update a browser kernel version"
2692
- )
2732
+ ),
2733
+ paramsDescription: schemaParamsDescription(schemas.downloadKernelSchema, "download-kernel")
2693
2734
  },
2694
2735
  "get-kernel-list": {
2695
2736
  fn: kernelHandlers.getKernelList,
2696
- description: buildCliCommandDescription("get-kernel-list", "Get browser kernel list by type or all")
2737
+ description: buildCliCommandDescription("get-kernel-list", "Get browser kernel list by type or all"),
2738
+ paramsDescription: schemaParamsDescription(schemas.getKernelListSchema, "get-kernel-list")
2697
2739
  },
2698
2740
  "update-patch": {
2699
2741
  fn: patchHandlers.updatePatch,
2700
- description: buildCliCommandDescription("update-patch", "Update AdsPower to latest patch version")
2742
+ description: buildCliCommandDescription("update-patch", "Update AdsPower to latest patch version"),
2743
+ paramsDescription: schemaParamsDescription(schemas.updatePatchSchema, "update-patch")
2701
2744
  }
2702
2745
  };
2703
2746
  var SINGLE_PROFILE_ID_COMMANDS = {
@@ -2765,10 +2808,242 @@ function resolveStartApiKey(optionApiKey, env = process.env) {
2765
2808
  };
2766
2809
  }
2767
2810
 
2811
+ // src/completion.ts
2812
+ var import_commander = __toESM(require("@bomb.sh/tab/commander"));
2813
+ var CLI_BIN_ALIASES = ["ads", "adspower", "adspower-browser"];
2814
+ function patchShellCompletionScript(shell, script) {
2815
+ if (shell === "zsh") {
2816
+ return script.replace(/^#compdef .+$/m, `#compdef ${CLI_BIN_ALIASES.join(" ")}`).replace(/^compdef _ads ads$/m, `compdef _ads ${CLI_BIN_ALIASES.join(" ")}`);
2817
+ }
2818
+ if (shell === "bash") {
2819
+ return script.replace(
2820
+ /^complete -F __ads_complete ads$/m,
2821
+ `complete -F __ads_complete ${CLI_BIN_ALIASES.join(" ")}`
2822
+ );
2823
+ }
2824
+ return script;
2825
+ }
2826
+ function setupShellCompletion(program2) {
2827
+ program2.name("ads");
2828
+ (0, import_commander.default)(program2);
2829
+ }
2830
+ function isShellCompletionRequest(argv = process.argv) {
2831
+ const completionIndex = argv.indexOf("complete");
2832
+ const dashDashIndex = argv.indexOf("--");
2833
+ return completionIndex !== -1 && dashDashIndex !== -1 && dashDashIndex > completionIndex;
2834
+ }
2835
+ function wrapShellScriptOutput(shell) {
2836
+ if (shell !== "zsh" && shell !== "bash") {
2837
+ return () => {
2838
+ };
2839
+ }
2840
+ const originalWrite = process.stdout.write.bind(process.stdout);
2841
+ process.stdout.write = ((chunk, encoding, callback) => {
2842
+ const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString(typeof encoding === "string" ? encoding : "utf8");
2843
+ const patched = patchShellCompletionScript(shell, text);
2844
+ if (typeof encoding === "function") {
2845
+ return originalWrite(patched, encoding);
2846
+ }
2847
+ return originalWrite(
2848
+ patched,
2849
+ encoding,
2850
+ callback
2851
+ );
2852
+ });
2853
+ return () => {
2854
+ process.stdout.write = originalWrite;
2855
+ };
2856
+ }
2857
+
2858
+ // src/handleAction.ts
2859
+ var readline = __toESM(require("readline/promises"));
2860
+ var import_colors2 = require("colors");
2861
+ var renderKernelProgress = (result) => {
2862
+ const status = result.status || "pending";
2863
+ const progress = ["completed", "installing"].includes(status) ? 100 : Math.max(0, Math.min(100, Number(result.progress) || 0));
2864
+ if (!process.stdout.isTTY) {
2865
+ logInfo(`Kernel progress: ${progress}% [${status}]`);
2866
+ return;
2867
+ }
2868
+ const width = 30;
2869
+ const filled = Math.round(progress / 100 * width);
2870
+ const bar = `${"=".repeat(filled)}${"-".repeat(width - filled)}`;
2871
+ process.stdout.write(`\r[${bar}] ${progress.toFixed(0).padStart(3, " ")}% ${status} `);
2872
+ };
2873
+ var finishKernelProgress = () => {
2874
+ if (process.stdout.isTTY) {
2875
+ process.stdout.write("\n");
2876
+ }
2877
+ };
2878
+ var trackKernelDownload = async (fnc, args) => {
2879
+ while (true) {
2880
+ const result = await fnc(args);
2881
+ try {
2882
+ const resultJson = JSON.parse(result);
2883
+ if (resultJson && resultJson.status && ["pending", "downloading", "completed", "installing", "failed"].includes(resultJson.status)) {
2884
+ renderKernelProgress(resultJson);
2885
+ if (["completed", "failed"].includes(resultJson.status)) {
2886
+ finishKernelProgress();
2887
+ return result;
2888
+ }
2889
+ await sleepTime(3e3);
2890
+ } else {
2891
+ return result;
2892
+ }
2893
+ } catch (error) {
2894
+ return result;
2895
+ }
2896
+ }
2897
+ };
2898
+ var handleAction = async (params, options, command, fnc) => {
2899
+ const isRun = await hasRunning(options);
2900
+ if (!isRun) {
2901
+ logError("[!] Adspower runtime is not running");
2902
+ const info = `[i] Please run "${(0, import_colors2.green)("adspower-browser start -k <apiKey>")}" to start the adspower runtime`;
2903
+ console.log(info);
2904
+ return;
2905
+ }
2906
+ const { apiKey, port } = getApiKeyAndPort(options);
2907
+ updateConfig(apiKey, port);
2908
+ const commandName = command.name();
2909
+ const resolved = resolveStatelessCommandArgs(commandName, params);
2910
+ if (!resolved.ok) {
2911
+ logError(resolved.error);
2912
+ return;
2913
+ }
2914
+ const args = resolved.args;
2915
+ logSuccess(`Executing command: ${commandName}, params: ${JSON.stringify(args)}`);
2916
+ const loading = createLoading(`Executing ${commandName}...`);
2917
+ try {
2918
+ if (commandName === "download-kernel") {
2919
+ loading.stop();
2920
+ const result = await trackKernelDownload(fnc, args);
2921
+ const out = typeof result === "string" ? result : JSON.stringify(result, null, 2);
2922
+ logInfo(`
2923
+
2924
+ ${out}
2925
+
2926
+ `);
2927
+ } else {
2928
+ const result = await fnc(args);
2929
+ const out = typeof result === "string" ? result : JSON.stringify(result, null, 2);
2930
+ loading.stop();
2931
+ logInfo(`
2932
+
2933
+ ${out}
2934
+ `);
2935
+ if (commandName === "update-patch" && !out.includes("The client is already on the latest patch version. No update is required")) {
2936
+ await sleepTime(1e3 * 60);
2937
+ await restartChild();
2938
+ }
2939
+ return out;
2940
+ }
2941
+ } catch (error) {
2942
+ loading.stop();
2943
+ const msg = error instanceof Error ? error.message : JSON.stringify(error);
2944
+ logError(`
2945
+ ${msg}
2946
+ `);
2947
+ await handleError(msg, commandName, params);
2948
+ } finally {
2949
+ loading.stop();
2950
+ }
2951
+ };
2952
+ var handleError = async (msg, commandName, params) => {
2953
+ if (commandName === "open-browser") {
2954
+ if (msg.includes("ready,please to download!")) {
2955
+ const reg = /(SunBrowser|FlowerBrowser) (\d+) is not ready,please to download!/;
2956
+ const match = msg.match(reg);
2957
+ if (match) {
2958
+ const kernelType = match[1] === "FlowerBrowser" ? "Firefox" : "Chrome";
2959
+ const kernelVersion = match[2];
2960
+ if (kernelType && kernelVersion) {
2961
+ const answer = await promptYesNo(`[?] Kernel ${match[1]} ${kernelVersion} is not ready. Download now?`);
2962
+ if (answer === "y") {
2963
+ const _params = { "kernel_type": kernelType, "kernel_version": kernelVersion };
2964
+ await handleAction(
2965
+ JSON.stringify(_params),
2966
+ {},
2967
+ { name: () => "download-kernel" },
2968
+ STATELESS_HANDLERS["download-kernel"].fn
2969
+ );
2970
+ await sleepTime(1e3 * 3);
2971
+ await handleAction(
2972
+ params,
2973
+ {},
2974
+ { name: () => "open-browser" },
2975
+ STATELESS_HANDLERS["open-browser"].fn
2976
+ );
2977
+ }
2978
+ }
2979
+ }
2980
+ }
2981
+ }
2982
+ if (commandName === "close-browser") {
2983
+ if (msg.includes("Profile does not exist")) {
2984
+ const answer = await promptYesNo(`[?] Profile does not exist. Check all opened profiles?`);
2985
+ if (answer === "y") {
2986
+ const result = await handleAction(
2987
+ "{}",
2988
+ {},
2989
+ { name: () => "get-opened-browser" },
2990
+ STATELESS_HANDLERS["get-opened-browser"].fn
2991
+ );
2992
+ if (result) {
2993
+ try {
2994
+ const data = JSON.parse(result);
2995
+ const userIds = data.list.map((item) => item.user_id);
2996
+ if (userIds.length === 1) {
2997
+ const answer2 = await promptYesNo(`[?] Only one opened profile. Close it now?`);
2998
+ if (answer2 === "y") {
2999
+ await handleAction(
3000
+ `{"profile_id":["${userIds[0]}"]}`,
3001
+ {},
3002
+ { name: () => "close-browser" },
3003
+ STATELESS_HANDLERS["close-browser"].fn
3004
+ );
3005
+ }
3006
+ } else if (userIds.length > 1) {
3007
+ logWarning(`[!] Closeable profiles: ${userIds.join(", ")}`);
3008
+ logWarning(`[!] If you want to close all profiles, please enter "ads close-all-profiles"`);
3009
+ }
3010
+ } catch (error) {
3011
+ console.error(error);
3012
+ }
3013
+ }
3014
+ }
3015
+ }
3016
+ }
3017
+ };
3018
+ async function promptYesNo(question) {
3019
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
3020
+ logWarning("[!] Interactive prompt is unavailable in non-interactive mode.");
3021
+ return null;
3022
+ }
3023
+ const rl = readline.createInterface({
3024
+ input: process.stdin,
3025
+ output: process.stdout
3026
+ });
3027
+ try {
3028
+ while (true) {
3029
+ const answer = (await rl.question(`${question} [y/N]: `)).trim().toLowerCase();
3030
+ if (answer === "y" || answer === "yes") {
3031
+ return "y";
3032
+ }
3033
+ if (answer === "n" || answer === "no" || answer === "") {
3034
+ return "n";
3035
+ }
3036
+ logWarning("[!] Please enter y or n.");
3037
+ }
3038
+ } finally {
3039
+ rl.close();
3040
+ }
3041
+ }
3042
+
2768
3043
  // src/index.ts
2769
- var program = new import_commander.Command();
2770
- program.name("adspower-browser").description("CLI and runtime for adspower-browser").version(VERSION);
2771
- program.command("start").description("Start the adspower runtime").option("-k, --api-key <apiKey>", "Set the API key for the adspower runtime").addOption(new import_commander.Option("--base-url <baseUrl>", "Set the base URL for the adspower runtime").hideHelp()).addOption(new import_commander.Option("--node-env <nodeEnv>", "Set the node environment for the adspower runtime").hideHelp()).action(async (options) => {
3044
+ var program = new import_commander2.Command();
3045
+ program.description("CLI and runtime for adspower-browser").version(VERSION);
3046
+ program.command("start").description("Start the adspower runtime").option("-k, --api-key <apiKey>", "Set the API key for the adspower runtime").addOption(new import_commander2.Option("--base-url <baseUrl>", "Set the base URL for the adspower runtime").hideHelp()).addOption(new import_commander2.Option("--node-env <nodeEnv>", "Set the node environment for the adspower runtime").hideHelp()).action(async (options) => {
2772
3047
  const resolvedApiKey = resolveStartApiKey(options.apiKey, process.env);
2773
3048
  if (!resolvedApiKey.ok) {
2774
3049
  logError(resolvedApiKey.error);
@@ -2794,53 +3069,19 @@ program.command("status").description("Get the status of the adspower runtime").
2794
3069
  });
2795
3070
  for (const cmd of Object.keys(STATELESS_HANDLERS)) {
2796
3071
  const fnc = STATELESS_HANDLERS[cmd].fn;
2797
- program.command(`${cmd} [params]`).description(STATELESS_HANDLERS[cmd].description).option("-k, --api-key <apiKey>", "Set the API key for the adspower runtime").option("-p, --port <port>", "Set the port for the adspower runtime").action(async (params, options, command) => {
2798
- const isRun = await hasRunning(options);
2799
- if (!isRun) {
2800
- logError("[!] Adspower runtime is not running");
2801
- const info = `[i] Please run "${(0, import_colors2.green)("adspower-browser start -k <apiKey>")}" to start the adspower runtime`;
2802
- console.log(info);
2803
- return;
2804
- }
2805
- const { apiKey, port } = getApiKeyAndPort(options);
2806
- updateConfig(apiKey, port);
2807
- const resolved = resolveStatelessCommandArgs(command.name(), params);
2808
- if (!resolved.ok) {
2809
- logError(resolved.error);
2810
- return;
2811
- }
2812
- const args = resolved.args;
2813
- logSuccess(`Executing command: ${command.name()}, params: ${JSON.stringify(args)}`);
2814
- const loading = createLoading(`Executing ${command.name()}...`);
2815
- try {
2816
- if (command.name() === "download-kernel") {
2817
- loading.stop();
2818
- const result = await trackKernelDownload(fnc, args);
2819
- const out = typeof result === "string" ? result : JSON.stringify(result, null, 2);
2820
- logInfo(`
2821
-
2822
- ${out}
2823
-
2824
- `);
2825
- } else {
2826
- const result = await fnc(args);
2827
- const out = typeof result === "string" ? result : JSON.stringify(result, null, 2);
2828
- logInfo(`
2829
-
2830
- ${out}
2831
- `);
2832
- if (command.name() === "update-patch" && !out.includes("The client is already on the latest patch version. No update is required")) {
2833
- loading.stop();
2834
- await sleepTime(1e3 * 60);
2835
- await restartChild();
2836
- }
2837
- }
2838
- } finally {
2839
- loading.stop();
2840
- }
3072
+ program.command(`${cmd}`).description(STATELESS_HANDLERS[cmd].description).option("-k, --api-key <apiKey>", "Set the API key for the adspower runtime").option("-p, --port <port>", "Set the port for the adspower runtime").argument("[params]", STATELESS_HANDLERS[cmd].paramsDescription).action(async (params, options, command) => {
3073
+ await handleAction(params, options, command, fnc);
2841
3074
  });
2842
3075
  }
2843
- program.parseAsync(process.argv).catch((error) => {
2844
- console.error(error);
2845
- process.exit(1);
2846
- });
3076
+ setupShellCompletion(program);
3077
+ var shellScriptArg = process.argv[2] === "complete" ? process.argv[3] : void 0;
3078
+ var restoreStdout = wrapShellScriptOutput(shellScriptArg);
3079
+ if (isShellCompletionRequest()) {
3080
+ program.parse(process.argv);
3081
+ restoreStdout();
3082
+ } else {
3083
+ program.parseAsync(process.argv).catch((error) => {
3084
+ console.error(error);
3085
+ process.exit(1);
3086
+ }).finally(restoreStdout);
3087
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adspower-browser",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
4
4
  "main": "cli/index.js",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -13,12 +13,13 @@
13
13
  "adspower": "node cli/index.js"
14
14
  },
15
15
  "dependencies": {
16
+ "@bomb.sh/tab": "^0.0.15",
16
17
  "axios": "^1.8.4",
17
18
  "colors": "^1.4.0",
18
19
  "commander": "^14.0.3",
19
20
  "fs-extra2": "^1.0.1",
20
21
  "playwright-core": "^1.51.1",
21
- "zod": "^3.24.2"
22
+ "zod": "^4.4.3"
22
23
  },
23
24
  "devDependencies": {
24
25
  "@adspower/local-api-core": "workspace:*",