adspower-browser 2.0.0-beta.0 → 2.0.0-beta.2

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 CHANGED
@@ -8,6 +8,16 @@ AdsPower browser automation CLI for AI agents.
8
8
  npm install -g adspower-browser
9
9
  ```
10
10
 
11
+ After installation, you can use any of these equivalent commands:
12
+
13
+ ```bash
14
+ adspower-browser
15
+ adspower
16
+ ads
17
+ ```
18
+
19
+ `adspower-browser` is the original command name. `adspower` and `ads` are aliases that point to the same CLI entry.
20
+
11
21
  ## Install as Cursor / Agent Skill
12
22
 
13
23
  Skills live at the repo root. Install with:
@@ -23,80 +33,120 @@ npx skills add AdsPower/adspower-browser
23
33
 
24
34
  Use the CLI in terminal or let the agent run it; the installed skill gives the agent context on when and how to call `adspower-browser` (profiles, groups, proxies, etc.).
25
35
 
26
-
27
36
  ## How to Run
28
37
 
38
+ The examples below use `ads` for brevity, but `adspower-browser` and `adspower` work the same way.
39
+
29
40
  ```bash
30
- adspower-browser [--port PORT] [--api-key KEY] <command> [<arg>]
41
+ ads start -k <KEY>
42
+ ```
43
+
44
+ If the `ADS_API_KEY` environment variable is set, you can start the CLI directly with the following command.
45
+
46
+ ```bash
47
+ ads start
31
48
  ```
32
49
 
33
50
  **Two forms for `<arg>`:**
34
51
 
35
52
  1. **Single value (shorthand)** — for profile-related commands, pass one profile ID or number:
36
- - `adspower-browser open-browser <ProfileId>`
37
- - `adspower-browser close-browser <ProfileId>`
38
- - `adspower-browser get-profile-cookies <ProfileId>`
39
- - `adspower-browser get-browser-active <ProfileId>`
40
- - `adspower-browser get-profile-ua <ProfileId>` (single ID)
41
- - `adspower-browser new-fingerprint <ProfileId>` (single ID)
53
+ - `ads open-browser <ProfileId>`
54
+ - `ads close-browser <ProfileId>`
55
+ - `ads get-profile-cookies <ProfileId>`
56
+ - `ads get-browser-active <ProfileId>`
57
+ - `ads get-profile-ua <ProfileId>` (single ID)
58
+ - `ads new-fingerprint <ProfileId>` (single ID)
42
59
 
43
60
  2. **JSON string** — full parameters for any command (see Command Reference below):
44
- - `adspower-browser open-browser '{"profileId":"abc123","launchArgs":"..."}'`
61
+ - `ads open-browser '{"profileId":"abc123","launchArgs":"..."}'`
45
62
  - Commands with no params: omit `<arg>` or use `'{}'`.
46
63
 
47
- ## Essential Commands
64
+ ## Essential Commands With CLI
65
+
66
+ You can use `ads -h` or `ads <command> -h` to view the specific parameters.
67
+
68
+ ### Start and stop CLI
69
+
70
+ ```bash
71
+ ads start -k <KEY> # Start the adspower runtime
72
+ ads stop # Stop the adspower runtime
73
+ ads restart # Restart the adspower runtime
74
+ ads status # Get the status of the adspower runtime
75
+ ```
48
76
 
49
77
  ### Browser profile – open/close
50
78
 
51
79
  ```bash
52
- adspower-browser open-browser <profileId> # Or JSON: profileId, profileNo?, ipTab?, launchArgs?, clearCacheAfterClosing?, cdpMask?
53
- adspower-browser close-browser <profileId> # Or JSON: profileId? | profileNo? (one required)
80
+ ads open-browser <profileId> # Or JSON: profileId, profileNo?, ipTab?, launchArgs?, clearCacheAfterClosing?, cdpMask?
81
+ ads close-browser <profileId> # Or JSON: profileId? | profileNo? (one required)
54
82
  ```
55
83
 
56
84
  ### Browser profile – create/update/delete/list
57
85
 
58
86
  ```bash
59
- adspower-browser create-browser '{"groupId":"0","proxyid":"random",...}' # groupId + account field + proxy required
60
- adspower-browser update-browser '{"profileId":"...",...}' # profileId required
61
- adspower-browser delete-browser '{"profileIds":["..."]}' # profileIds required
62
- adspower-browser get-browser-list '{}' # Or groupId?, limit?, page?, profileId?, profileNo?, sortType?, sortOrder?
63
- adspower-browser get-opened-browser # No params
87
+ ads create-browser '{"groupId":"0","proxyid":"random",...}' # groupId + account field + proxy required
88
+ ads update-browser '{"profileId":"...",...}' # profileId required
89
+ ads delete-browser '{"profileIds":["..."]}' # profileIds required
90
+ ads get-browser-list '{}' # Or groupId?, limit?, page?, profileId?, profileNo?, sortType?, sortOrder?
91
+ ads get-opened-browser # No params
64
92
  ```
65
93
 
66
94
  ### Browser profile – move/cookies/UA/fingerprint/cache/share/active
67
95
 
68
96
  ```bash
69
- adspower-browser move-browser '{"groupId":"1","userIds":["..."]}' # groupId + userIds required
70
- adspower-browser get-profile-cookies <profileId> # Or JSON: profileId? | profileNo?
71
- adspower-browser get-profile-ua <profileId> # Or JSON: profileId[]? | profileNo[]? (up to 10)
72
- adspower-browser close-all-profiles # No params
73
- adspower-browser new-fingerprint <profileId> # Or JSON: profileId[]? | profileNo[]? (up to 10)
74
- adspower-browser delete-cache-v2 '{"profileIds":["..."],"type":["cookie","history"]}' # type: local_storage|indexeddb|extension_cache|cookie|history|image_file
75
- adspower-browser share-profile '{"profileIds":["..."],"receiver":"email@example.com"}' # receiver required; shareType?, content?
76
- adspower-browser get-browser-active <profileId> # Or JSON: profileId? | profileNo?
77
- adspower-browser get-cloud-active '{"userIds":"id1,id2"}' # userIds comma-separated, max 100
97
+ ads move-browser '{"groupId":"1","userIds":["..."]}' # groupId + userIds required
98
+ ads get-profile-cookies <profileId> # Or JSON: profileId? | profileNo?
99
+ ads get-profile-ua <profileId> # Or JSON: profileId[]? | profileNo[]? (up to 10)
100
+ ads close-all-profiles # No params
101
+ ads new-fingerprint <profileId> # Or JSON: profileId[]? | profileNo[]? (up to 10)
102
+ ads delete-cache-v2 '{"profileIds":["..."],"type":["cookie","history"]}' # type: local_storage|indexeddb|extension_cache|cookie|history|image_file
103
+ ads share-profile '{"profileIds":["..."],"receiver":"email@example.com"}' # receiver required; shareType?, content?
104
+ ads get-browser-active <profileId> # Or JSON: profileId? | profileNo?
105
+ ads get-cloud-active '{"userIds":"id1,id2"}' # userIds comma-separated, max 100
78
106
  ```
79
107
 
80
108
  ### Group
81
109
 
82
110
  ```bash
83
- adspower-browser create-group '{"groupName":"My Group","remark":"..."}' # groupName required
84
- adspower-browser update-group '{"groupId":"1","groupName":"New Name"}' # groupId + groupName required; remark? (null to clear)
85
- adspower-browser get-group-list '{}' # groupName?, size?, page?
111
+ ads create-group '{"groupName":"My Group","remark":"..."}' # groupName required
112
+ ads update-group '{"groupId":"1","groupName":"New Name"}' # groupId + groupName required; remark? (null to clear)
113
+ ads get-group-list '{}' # groupName?, size?, page?
86
114
  ```
87
115
 
88
116
  ### Application (categories)
89
117
 
90
118
  ```bash
91
- adspower-browser check-status # No params – API availability
92
- adspower-browser get-application-list '{}' # category_id?, page?, limit?
119
+ ads check-status # No params – API availability
120
+ ads get-application-list '{}' # category_id?, page?, limit?
93
121
  ```
94
122
 
95
123
  ### Proxy
96
124
 
97
125
  ```bash
98
- adspower-browser create-proxy '{"proxies":[{"type":"http","host":"127.0.0.1","port":"8080"}]}' # type, host, port required per item
99
- adspower-browser update-proxy '{"proxyId":"...","host":"..."}' # proxyId required
100
- adspower-browser get-proxy-list '{}' # limit?, page?, proxyId?
101
- adspower-browser delete-proxy '{"proxyIds":["..."]}' # proxyIds required, max 100
126
+ ads create-proxy '{"proxies":[{"type":"http","host":"127.0.0.1","port":"8080"}]}' # type, host, port required per item
127
+ ads update-proxy '{"proxyId":"...","host":"..."}' # proxyId required
128
+ ads get-proxy-list '{}' # limit?, page?, proxyId?
129
+ ads delete-proxy '{"proxyIds":["..."]}' # proxyIds required, max 100
102
130
  ```
131
+
132
+ ### Tag
133
+
134
+ ```bash
135
+ ads get-tag-list '{}' # limit?, page?, ids?
136
+ ads create-tag '{"tags":[{"name":"test","color":"darkBlue"}]}' # name required, color?: darkBlue|blue|purple|red|yellow|orange|green|lightGreen
137
+ ads update-tag '{"tags":[{"id":"...","name":"test2","color":"yellow"}]}' # id required,name?, color?: darkBlue|blue|purple|red|yellow|orange|green|lightGreen
138
+ ads delete-tag '{"ids":["..."]}' # ids required, max 100
139
+ ```
140
+
141
+ ### Kernel
142
+
143
+ ```bash
144
+ ads get-kernel-list '{"kernel_type":"Chrome"}' # kernel_type?:Chrome|Firefox
145
+ ads download-kernel '{"kernel_type":"Chrome","kernel_version":"..."}' # kernel_type:Chrome|Firefox required,kernel_version required
146
+ ```
147
+
148
+ ### Update Patch
149
+
150
+ ```bash
151
+ ads update-patch '{"version_type":"stable"}' # version_type?:stable|beta
152
+ ```
package/cli/index.js CHANGED
@@ -53,6 +53,9 @@ var Store = class {
53
53
  this.pid = "";
54
54
  }
55
55
  getStoreValue(key) {
56
+ if (key === "apiKey" && !this.apiKey) {
57
+ return process.env.ADS_API_KEY || "";
58
+ }
56
59
  return this[key];
57
60
  }
58
61
  setStoreValue(key, value) {
@@ -205,8 +208,12 @@ var getApiKeyAndPort = (options) => {
205
208
  port
206
209
  };
207
210
  const processInstance = readPidFile();
208
- if (!apiKey && processInstance.apiKey) {
209
- result.apiKey = processInstance.apiKey;
211
+ if (!apiKey) {
212
+ if (processInstance.apiKey) {
213
+ result.apiKey = processInstance.apiKey;
214
+ } else if (process.env.ADS_API_KEY) {
215
+ result.apiKey = process.env.ADS_API_KEY;
216
+ }
210
217
  }
211
218
  if (!port && processInstance.apiPort) {
212
219
  result.port = processInstance.apiPort;
@@ -274,6 +281,43 @@ var initSqlite3 = () => {
274
281
  logSuccess(`[i] SQLite file initialized successfully!`);
275
282
  }
276
283
  };
284
+ var renderKernelProgress = (result) => {
285
+ const status = result.status || "pending";
286
+ const progress = ["completed", "installing"].includes(status) ? 100 : Math.max(0, Math.min(100, Number(result.progress) || 0));
287
+ if (!process.stdout.isTTY) {
288
+ logInfo(`Kernel progress: ${progress}% [${status}]`);
289
+ return;
290
+ }
291
+ const width = 30;
292
+ const filled = Math.round(progress / 100 * width);
293
+ const bar = `${"=".repeat(filled)}${"-".repeat(width - filled)}`;
294
+ process.stdout.write(`\r[${bar}] ${progress.toFixed(0).padStart(3, " ")}% ${status} `);
295
+ };
296
+ var finishKernelProgress = () => {
297
+ if (process.stdout.isTTY) {
298
+ process.stdout.write("\n");
299
+ }
300
+ };
301
+ var trackKernelDownload = async (fnc, args) => {
302
+ while (true) {
303
+ const result = await fnc(args);
304
+ try {
305
+ const resultJson = JSON.parse(result.replace("Kernel download/update status: ", ""));
306
+ if (resultJson && resultJson.status && ["pending", "downloading", "completed", "installing", "failed"].includes(resultJson.status)) {
307
+ renderKernelProgress(resultJson);
308
+ if (["completed", "failed"].includes(resultJson.status)) {
309
+ finishKernelProgress();
310
+ return result;
311
+ }
312
+ await sleepTime(3e3);
313
+ } else {
314
+ return result;
315
+ }
316
+ } catch (error) {
317
+ return result;
318
+ }
319
+ }
320
+ };
277
321
 
278
322
  // src/core/start.ts
279
323
  var getEnv = () => {
@@ -511,7 +555,7 @@ function parseArgs() {
511
555
  }
512
556
  }
513
557
  return {
514
- port: port || process.env.PORT || "50326",
558
+ port: port || process.env.PORT || "50325",
515
559
  apiKey: apiKey || process.env.API_KEY
516
560
  };
517
561
  }
@@ -2048,9 +2092,16 @@ var SINGLE_PROFILE_ID_ARRAY_COMMANDS = ["get-profile-ua", "new-fingerprint"];
2048
2092
  // src/index.ts
2049
2093
  var program = new import_commander.Command();
2050
2094
  program.name("adspower-browser").description("CLI and runtime for adspower-browser").version(VERSION);
2051
- program.command("start").description("Start the adspower runtime").requiredOption("-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) => {
2095
+ 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) => {
2052
2096
  if (options.apiKey) {
2053
2097
  store.setStoreValue("apiKey", options.apiKey);
2098
+ } else {
2099
+ const apiKey = process.env.ADS_API_KEY;
2100
+ if (!apiKey) {
2101
+ logError("error: required option '-k, --api-key <apiKey>' not specified");
2102
+ process.exit(1);
2103
+ }
2104
+ store.setStoreValue("apiKey", "");
2054
2105
  }
2055
2106
  if (options.baseUrl) {
2056
2107
  store.setStoreValue("baseUrl", options.baseUrl);
@@ -2112,15 +2163,27 @@ for (const cmd of Object.keys(STATELESS_HANDLERS)) {
2112
2163
  logSuccess(`Executing command: ${command.name()}, params: ${JSON.stringify(args)}`);
2113
2164
  const loading = createLoading(`Executing ${command.name()}...`);
2114
2165
  try {
2115
- const result = await fnc(args);
2116
- const out = typeof result === "string" ? result : JSON.stringify(result, null, 2);
2117
- logInfo(`
2166
+ if (command.name() === "download-kernel") {
2167
+ loading.stop();
2168
+ const result = await trackKernelDownload(fnc, args);
2169
+ const out = typeof result === "string" ? result : JSON.stringify(result, null, 2);
2170
+ logInfo(`
2171
+
2172
+ ${out}
2173
+
2174
+ `);
2175
+ } else {
2176
+ const result = await fnc(args);
2177
+ const out = typeof result === "string" ? result : JSON.stringify(result, null, 2);
2178
+ logInfo(`
2118
2179
 
2119
2180
  ${out}
2120
2181
  `);
2121
- if (command.name() === "update-patch") {
2122
- await sleepTime(1e3 * 60);
2123
- await restartChild();
2182
+ if (command.name() === "update-patch" && !out.includes("The client is already on the latest patch version. No update is required")) {
2183
+ loading.stop();
2184
+ await sleepTime(1e3 * 60);
2185
+ await restartChild();
2186
+ }
2124
2187
  }
2125
2188
  } finally {
2126
2189
  loading.stop();