adspower-browser 1.0.2 → 2.0.0-beta.1

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.
@@ -23,6 +23,521 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
23
  mod
24
24
  ));
25
25
 
26
+ // src/index.ts
27
+ var import_commander = require("commander");
28
+
29
+ // src/store/index.ts
30
+ var Store = class {
31
+ apiKey;
32
+ baseUrl;
33
+ nodeEnv;
34
+ apiPort;
35
+ appPort;
36
+ intranet;
37
+ rpaPid;
38
+ rpaPlusPid;
39
+ aiPid;
40
+ status;
41
+ pid;
42
+ constructor() {
43
+ this.apiKey = "";
44
+ this.baseUrl = "";
45
+ this.nodeEnv = "";
46
+ this.apiPort = "";
47
+ this.appPort = "";
48
+ this.intranet = "";
49
+ this.rpaPid = "";
50
+ this.rpaPlusPid = "";
51
+ this.aiPid = "";
52
+ this.status = "stop";
53
+ this.pid = "";
54
+ }
55
+ getStoreValue(key) {
56
+ if (key === "apiKey" && !this.apiKey) {
57
+ return process.env.ADS_API_KEY || "";
58
+ }
59
+ return this[key];
60
+ }
61
+ setStoreValue(key, value) {
62
+ this[key] = value;
63
+ }
64
+ clear() {
65
+ this.apiKey = "";
66
+ this.baseUrl = "";
67
+ this.nodeEnv = "";
68
+ this.apiPort = "";
69
+ this.appPort = "";
70
+ this.intranet = "";
71
+ this.rpaPid = "";
72
+ this.rpaPlusPid = "";
73
+ this.aiPid = "";
74
+ this.status = "stop";
75
+ this.pid = "";
76
+ }
77
+ getAllStoreValue() {
78
+ return {
79
+ apiKey: this.apiKey,
80
+ baseUrl: this.baseUrl,
81
+ nodeEnv: this.nodeEnv,
82
+ apiPort: this.apiPort,
83
+ appPort: this.appPort,
84
+ intranet: this.intranet,
85
+ rpaPid: this.rpaPid,
86
+ rpaPlusPid: this.rpaPlusPid,
87
+ aiPid: this.aiPid,
88
+ status: this.status,
89
+ pid: this.pid
90
+ };
91
+ }
92
+ };
93
+ var store = new Store();
94
+
95
+ // src/core/start.ts
96
+ var path2 = __toESM(require("path"));
97
+ var import_node_child_process2 = require("child_process");
98
+
99
+ // src/tools/index.ts
100
+ var os = __toESM(require("os"));
101
+ var path = __toESM(require("path"));
102
+ var fs = __toESM(require("fs"));
103
+ var crypto = __toESM(require("crypto"));
104
+ var util = __toESM(require("util"));
105
+ var import_node_child_process = require("child_process");
106
+ var import_colors = require("colors");
107
+ var import_fs_extra2 = require("fs-extra2");
108
+ var VERSION = "1.0.0";
109
+ var logError = (message) => {
110
+ console.error((0, import_colors.red)(message));
111
+ };
112
+ var logSuccess = (message) => {
113
+ console.log((0, import_colors.green)(message));
114
+ };
115
+ var logWarning = (message) => {
116
+ console.log((0, import_colors.yellow)(message));
117
+ };
118
+ var logInfo = (message) => {
119
+ console.log(message);
120
+ };
121
+ var sleepTime = (time) => new Promise((resolve) => {
122
+ setTimeout(() => {
123
+ resolve();
124
+ }, time);
125
+ });
126
+ var browsersKill = async () => {
127
+ await taskKillBrowser();
128
+ await taskKillFlowser();
129
+ };
130
+ var taskKillBrowser = () => new Promise((resolve) => {
131
+ const cmd = ["linux", "darwin"].includes(process.platform) ? 'pkill -u `whoami` -f "SunBrowser"' : "taskkill -PID SunBrowser.exe";
132
+ (0, import_node_child_process.exec)(cmd, (err) => {
133
+ if (err) {
134
+ }
135
+ resolve();
136
+ });
137
+ });
138
+ var taskKillFlowser = () => new Promise((resolve) => {
139
+ const cmd = ["linux", "darwin"].includes(process.platform) ? 'pkill -u `whoami` -f "FlowerBrowser"' : "taskkill -PID FlowerBrowser.exe";
140
+ (0, import_node_child_process.exec)(cmd, (err) => {
141
+ if (err) {
142
+ }
143
+ resolve();
144
+ });
145
+ });
146
+ var getHomedir = () => {
147
+ return (typeof os.homedir == "function" ? os.homedir() : process.env[process.platform == "win32" ? "USERPROFILE" : "HOME"]) || "~";
148
+ };
149
+ var getPidFileDir = () => {
150
+ const dir = path.join(getHomedir(), ".adspowerCli");
151
+ if (!fs.existsSync(dir)) {
152
+ (0, import_fs_extra2.ensureDirSync)(dir);
153
+ }
154
+ return dir;
155
+ };
156
+ var pidFileName = () => {
157
+ const md5 = crypto.createHash("md5").update(VERSION).digest("hex");
158
+ return md5;
159
+ };
160
+ var writePidFile = (config2) => {
161
+ const filePath = path.join(getPidFileDir(), pidFileName());
162
+ (0, import_fs_extra2.outputJsonSync)(filePath, config2 || {});
163
+ };
164
+ var readPidFile = () => {
165
+ const filePath = path.join(getPidFileDir(), pidFileName());
166
+ if (fs.existsSync(filePath)) {
167
+ return (0, import_fs_extra2.readJsonSync)(filePath);
168
+ }
169
+ return {};
170
+ };
171
+ var removePidFile = () => {
172
+ const filePath = path.join(getPidFileDir(), pidFileName());
173
+ if (fs.existsSync(filePath)) {
174
+ (0, import_fs_extra2.removeSync)(filePath);
175
+ }
176
+ };
177
+ var isRunning = (pid) => {
178
+ return new Promise((resolve) => {
179
+ if (pid) {
180
+ (0, import_node_child_process.exec)(
181
+ util.format(process.platform === "win32" ? 'tasklist /fi "PID eq %s" | findstr /i "node.exe"' : 'ps -f -p %s | grep "node"', pid),
182
+ function(err, stdout, stderr) {
183
+ resolve(!err && !!stdout.toString().trim());
184
+ }
185
+ );
186
+ } else {
187
+ resolve(false);
188
+ }
189
+ });
190
+ };
191
+ var ensureBrowserPath = () => {
192
+ const dir = path.join(__dirname, "../cwd/source", ".browser");
193
+ if (!fs.existsSync(dir)) {
194
+ (0, import_fs_extra2.ensureDirSync)(dir);
195
+ }
196
+ };
197
+ var getApiKeyAndPort = (options) => {
198
+ const apiKey = options.apiKey;
199
+ const port = options.port;
200
+ if (apiKey && port) {
201
+ return {
202
+ apiKey,
203
+ port
204
+ };
205
+ }
206
+ const result = {
207
+ apiKey,
208
+ port
209
+ };
210
+ const processInstance = readPidFile();
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
+ }
217
+ }
218
+ if (!port && processInstance.apiPort) {
219
+ result.port = processInstance.apiPort;
220
+ }
221
+ return result;
222
+ };
223
+ var hasRunning = async (options) => {
224
+ const { apiKey, port } = options;
225
+ if (apiKey && port) {
226
+ return true;
227
+ }
228
+ const processInstance = readPidFile();
229
+ if (processInstance.pid) {
230
+ return await isRunning(processInstance.pid);
231
+ }
232
+ return false;
233
+ };
234
+ var loadingFramesList = {
235
+ default: ["|", "/", "-", "\\"],
236
+ frames: ["\u2596", "\u2597", "\u2598", "\u2599", "\u259A", "\u259B", "\u259C", "\u259D", "\u259E", "\u259F"],
237
+ dotFrames: ["\u2840", "\u2844", "\u2846", "\u2847", "\u284F", "\u285F", "\u287F", "\u28FF", "\u28F7", "\u28F6", "\u28E6", "\u28E4", "\u28E0", "\u2880"]
238
+ };
239
+ var createLoading = (text) => {
240
+ if (!process.stdout.isTTY) {
241
+ return {
242
+ stop() {
243
+ }
244
+ };
245
+ }
246
+ let index = 0;
247
+ const frames = loadingFramesList.default;
248
+ process.stdout.write(`${frames[index]} ${text}`);
249
+ const timer = setInterval(() => {
250
+ index = (index + 1) % frames.length;
251
+ process.stdout.write(`\r${frames[index]} ${text}`);
252
+ }, 120);
253
+ return {
254
+ stop() {
255
+ clearInterval(timer);
256
+ process.stdout.write(`\r${" ".repeat(text.length + 2)}\r`);
257
+ }
258
+ };
259
+ };
260
+ var initSqlite3 = () => {
261
+ const sqliteFile = path.join(__dirname, "../cwd/lib", "node_sqlite3.node");
262
+ if (fs.existsSync(sqliteFile)) {
263
+ return;
264
+ }
265
+ const isMac = process.platform === "darwin";
266
+ const isLinux = process.platform === "linux";
267
+ const is32 = process.arch === "ia32";
268
+ const isArm = process.arch === "arm64";
269
+ const isX64 = process.arch === "x64";
270
+ const macFolder = isArm ? "arm64" : "mac";
271
+ const winFolder = is32 ? "ia32" : "x64";
272
+ const linuxFolder = isLinux && isX64 && "linux";
273
+ const sqliteFolder = isMac ? macFolder : isLinux ? linuxFolder : winFolder;
274
+ const dir = path.join(__dirname, `../sqlite/${sqliteFolder}`);
275
+ if (!fs.existsSync(dir)) {
276
+ throw new Error(`SQLite folder not found: ${dir}`);
277
+ } else {
278
+ const sqliteFile2 = path.join(dir, "node_sqlite3.node");
279
+ const cwdPath = path.join(__dirname, "../cwd/lib");
280
+ (0, import_fs_extra2.copySync)(sqliteFile2, path.join(cwdPath, "node_sqlite3.node"));
281
+ logSuccess(`[i] SQLite file initialized successfully!`);
282
+ }
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
+ };
321
+
322
+ // src/core/start.ts
323
+ var getEnv = () => {
324
+ const env = {
325
+ ...process.env,
326
+ // 系统的环境变量信息
327
+ API_KEY: store.getStoreValue("apiKey"),
328
+ IS_CLOUD_BROWSER: true
329
+ // 云浏览器场景预留标识
330
+ };
331
+ if (store.getStoreValue("baseUrl")) {
332
+ env.BASE_URL = store.getStoreValue("baseUrl");
333
+ }
334
+ if (store.getStoreValue("nodeEnv")) {
335
+ env.NODE_ENV = store.getStoreValue("nodeEnv");
336
+ }
337
+ return env;
338
+ };
339
+ var startChild = (type) => {
340
+ let timer;
341
+ let child = null;
342
+ return new Promise(async (resolve, reject) => {
343
+ initSqlite3();
344
+ const processInstance = readPidFile();
345
+ if (processInstance && processInstance.pid) {
346
+ const isRun = await isRunning(processInstance.pid);
347
+ removePidFile();
348
+ if (isRun) {
349
+ process.kill(Number(processInstance.pid), "SIGKILL");
350
+ await sleepTime(1e3);
351
+ }
352
+ }
353
+ const env = Object.fromEntries(
354
+ Object.entries(getEnv()).map(([key, value]) => [key, value == null ? value : String(value)])
355
+ );
356
+ try {
357
+ const mainJs = path2.join(__dirname, "../cwd/lib", "main.min.js");
358
+ child = (0, import_node_child_process2.fork)(mainJs, {
359
+ env,
360
+ detached: true,
361
+ stdio: ["ignore", "ignore", "ignore", "ipc"]
362
+ });
363
+ ensureBrowserPath();
364
+ store.setStoreValue("status", "starting");
365
+ logSuccess(`[i] Adspower program is starting...`);
366
+ store.setStoreValue("pid", child?.pid?.toString() || "");
367
+ let isAppPortOk = false;
368
+ writePidFile(store.getAllStoreValue());
369
+ child.on("message", async (msg) => {
370
+ const text = String(msg);
371
+ if (text.indexOf("SERVER_PORT_$$_") === 0 && !isAppPortOk) {
372
+ const port = text.replace("SERVER_PORT_$$_", "").trim();
373
+ store.setStoreValue("appPort", port);
374
+ isAppPortOk = true;
375
+ }
376
+ if (text.indexOf("START_API_SERVER_SUCCESS_$$_") === 0) {
377
+ const port = text.replace("START_API_SERVER_SUCCESS_$$_", "").trim();
378
+ store.setStoreValue("apiPort", port);
379
+ logSuccess(`Server running at:`);
380
+ logSuccess(` - local: http://local.adspower.net:${port}`);
381
+ writePidFile(store.getAllStoreValue());
382
+ if (child) {
383
+ child.disconnect();
384
+ child.unref();
385
+ }
386
+ }
387
+ if (text.indexOf("START_API_SERVER_FAIL_$$_") === 0) {
388
+ const serverMsg = text.replace("START_API_SERVER_FAIL_$$_", "").split("_").filter(Boolean);
389
+ if (serverMsg[0]) {
390
+ logError(`ERROR - ${serverMsg[0]}`);
391
+ }
392
+ if (serverMsg[1]) {
393
+ logError(`ERROR - ${serverMsg[1]}`);
394
+ }
395
+ process.exit(0);
396
+ }
397
+ if (text === "start") {
398
+ clearTimeout(timer);
399
+ resolve();
400
+ store.setStoreValue("status", "doing");
401
+ writePidFile(store.getAllStoreValue());
402
+ }
403
+ if (text === "restart") {
404
+ child && child.kill("SIGKILL");
405
+ store.setStoreValue("status", "restarting");
406
+ startChild("2").catch(() => {
407
+ });
408
+ }
409
+ if (text.indexOf("INTRANET_$$_") > -1) {
410
+ const arr = text.split("_$$_");
411
+ if (arr && arr[1]) {
412
+ store.setStoreValue("intranet", arr[1]);
413
+ }
414
+ }
415
+ if (text === "browser-kill") {
416
+ await browsersKill();
417
+ }
418
+ if (text.indexOf("RPA_PROCESS_PID_") > -1) {
419
+ const rpaPid = text.replace("RPA_PROCESS_PID_", "");
420
+ store.setStoreValue("rpaPid", rpaPid);
421
+ }
422
+ if (text.indexOf("RPA_PLUS_PROCESS_PID_") > -1) {
423
+ const rpaPlusPid = text.replace("RPA_PLUS_PROCESS_PID_", "");
424
+ store.setStoreValue("rpaPlusPid", rpaPlusPid);
425
+ }
426
+ if (text.indexOf("AI_PROCESS_PID_") > -1) {
427
+ const aiPid = text.replace("AI_PROCESS_PID_", "");
428
+ store.setStoreValue("aiPid", aiPid);
429
+ }
430
+ });
431
+ child.on("error", (err) => {
432
+ logError(`[!] Node\u542F\u52A8\u5931\u8D25: ${err.message}`);
433
+ store.setStoreValue("status", "stop");
434
+ store.clear();
435
+ removePidFile();
436
+ process.exit(0);
437
+ });
438
+ child.on("exit", async (code, signal) => {
439
+ if (signal === "SIGKILL") {
440
+ await browsersKill();
441
+ store.clear();
442
+ removePidFile();
443
+ } else {
444
+ child = null;
445
+ await sleepTime(500);
446
+ startChild("2").then(() => {
447
+ }).catch(() => {
448
+ logError("[!] Restart failed");
449
+ });
450
+ }
451
+ });
452
+ timer = setTimeout(() => {
453
+ child && child.kill("SIGKILL");
454
+ child = null;
455
+ store.setStoreValue("status", "stop");
456
+ logError("[!] Start Timeout");
457
+ reject("Start Timeout");
458
+ }, 30 * 1e3);
459
+ } catch (error) {
460
+ clearTimeout(timer);
461
+ reject(error);
462
+ child = null;
463
+ store.clear();
464
+ logError(`[!] Node\u542F\u52A8\u5931\u8D25: ${error instanceof Error ? error.message : JSON.stringify(error)}`);
465
+ }
466
+ });
467
+ };
468
+ var stopChild = async () => {
469
+ const processInstance = readPidFile();
470
+ if (processInstance.pid) {
471
+ const isRun = await isRunning(processInstance.pid);
472
+ try {
473
+ process.kill(Number(processInstance.pid), "SIGKILL");
474
+ removePidFile();
475
+ } catch (error) {
476
+ try {
477
+ await sleepTime(2e3);
478
+ process.kill(Number(processInstance.pid), "SIGKILL");
479
+ removePidFile();
480
+ } catch (error2) {
481
+ logError(`[!] Stop child fail: ${error2 instanceof Error ? error2.message : JSON.stringify(error2)}`);
482
+ if (isRun) {
483
+ logWarning(`[!] Please manually close the browser process: ${processInstance.pid}`);
484
+ }
485
+ return;
486
+ }
487
+ }
488
+ logSuccess("[i] Adspower program is stopped");
489
+ } else {
490
+ logInfo("[i] No running adspower program");
491
+ }
492
+ };
493
+ var restartChild = async () => {
494
+ const processInstance = readPidFile();
495
+ if (processInstance.pid) {
496
+ const apiKey = processInstance.apiKey;
497
+ const baseUrl = processInstance.baseUrl;
498
+ const nodeEnv = processInstance.nodeEnv;
499
+ await stopChild();
500
+ await sleepTime(1e3);
501
+ store.setStoreValue("apiKey", apiKey);
502
+ store.setStoreValue("baseUrl", baseUrl);
503
+ store.setStoreValue("nodeEnv", nodeEnv);
504
+ await startChild().then(() => {
505
+ logSuccess("[i] Adspower program is restarted");
506
+ }).catch((error) => {
507
+ logError(`[!] Restart failed: ${error.message}`);
508
+ });
509
+ } else {
510
+ logInfo("[i] No running adspower program");
511
+ }
512
+ };
513
+ var getChildStatus = async () => {
514
+ const processInstance = readPidFile();
515
+ if (processInstance.pid) {
516
+ const isRun = await isRunning(processInstance.pid);
517
+ if (!isRun) {
518
+ removePidFile();
519
+ logInfo("[i] Adspower program is not running");
520
+ return;
521
+ }
522
+ const status = processInstance.status;
523
+ if (status === "starting") {
524
+ logSuccess("[i] Adspower program is starting...");
525
+ } else if (status === "doing" && processInstance.apiPort) {
526
+ logSuccess("[i] Adspower program is running at:");
527
+ logSuccess(` - http://local.adspower.net:${processInstance.apiPort}`);
528
+ } else if (status === "stop") {
529
+ logInfo("[i] Adspower program is stopped");
530
+ } else {
531
+ logInfo("[i] Adspower program is not started");
532
+ }
533
+ } else {
534
+ logInfo("[i] Adspower program is not running");
535
+ }
536
+ };
537
+
538
+ // src/index.ts
539
+ var import_colors2 = require("colors");
540
+
26
541
  // ../core/src/constants/api.ts
27
542
  var import_axios = __toESM(require("axios"));
28
543
 
@@ -40,16 +555,28 @@ function parseArgs() {
40
555
  }
41
556
  }
42
557
  return {
43
- port: port || process.env.PORT || "50325",
558
+ port: port || process.env.PORT || "50326",
44
559
  apiKey: apiKey || process.env.API_KEY
45
560
  };
46
561
  }
47
562
  var config = parseArgs();
563
+ var updateConfig = (apiKey, port) => {
564
+ if (apiKey) {
565
+ config.apiKey = apiKey;
566
+ }
567
+ if (port) {
568
+ config.port = port;
569
+ }
570
+ };
48
571
  var PORT = config.port;
49
572
  var API_KEY = config.apiKey;
573
+ var CONFIG = config;
50
574
 
51
575
  // ../core/src/constants/api.ts
52
576
  var LOCAL_API_BASE = `http://127.0.0.1:${PORT}`;
577
+ var getLocalApiBase = () => {
578
+ return `http://127.0.0.1:${CONFIG.port}`;
579
+ };
53
580
  var API_ENDPOINTS = {
54
581
  STATUS: "/status",
55
582
  START_BROWSER: "/api/v2/browser-profile/start",
@@ -87,6 +614,11 @@ var API_ENDPOINTS = {
87
614
  var apiClient = import_axios.default.create({
88
615
  headers: API_KEY ? { "Authorization": `Bearer ${API_KEY}` } : {}
89
616
  });
617
+ var getApiClient = () => {
618
+ return import_axios.default.create({
619
+ headers: CONFIG.apiKey ? { "Authorization": `Bearer ${CONFIG.apiKey}` } : {}
620
+ });
621
+ };
90
622
 
91
623
  // ../core/src/utils/requestBuilder.ts
92
624
  function buildRequestBody(params) {
@@ -174,7 +706,7 @@ var browserHandlers = {
174
706
  if (cdpMask) {
175
707
  requestBody.cdp_mask = cdpMask;
176
708
  }
177
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.START_BROWSER}`, requestBody);
709
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.START_BROWSER}`, requestBody);
178
710
  if (response.data.code === 0) {
179
711
  return `Browser opened successfully with: ${Object.entries(response.data.data).map(([key, value]) => {
180
712
  if (value && typeof value === "object") {
@@ -193,7 +725,7 @@ var browserHandlers = {
193
725
  if (profileNo) {
194
726
  requestBody.profile_no = profileNo;
195
727
  }
196
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.CLOSE_BROWSER}`, requestBody);
728
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CLOSE_BROWSER}`, requestBody);
197
729
  if (response.data.code === 0) {
198
730
  return "Browser closed successfully";
199
731
  }
@@ -201,7 +733,7 @@ var browserHandlers = {
201
733
  },
202
734
  async createBrowser(params) {
203
735
  const requestBody = buildRequestBody(params);
204
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.CREATE_BROWSER}`, requestBody);
736
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CREATE_BROWSER}`, requestBody);
205
737
  if (response.data.code === 0) {
206
738
  return `Browser created successfully with: ${Object.entries(response.data.data).map(([key, value]) => `${key}: ${value}`).join("\n")}`;
207
739
  }
@@ -209,14 +741,14 @@ var browserHandlers = {
209
741
  },
210
742
  async updateBrowser(params) {
211
743
  const requestBody = buildRequestBody(params);
212
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.UPDATE_BROWSER}`, requestBody);
744
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_BROWSER}`, requestBody);
213
745
  if (response.data.code === 0) {
214
746
  return `Browser updated successfully with: ${Object.entries(response.data.data || {}).map(([key, value]) => `${key}: ${value}`).join("\n")}`;
215
747
  }
216
748
  throw new Error(`Failed to update browser: ${response.data.msg}`);
217
749
  },
218
750
  async deleteBrowser({ profileIds }) {
219
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.DELETE_BROWSER}`, {
751
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.DELETE_BROWSER}`, {
220
752
  profile_id: profileIds
221
753
  });
222
754
  if (response.data.code === 0) {
@@ -260,21 +792,21 @@ var browserHandlers = {
260
792
  if (name_filter) {
261
793
  requestBody.name_filter = name_filter;
262
794
  }
263
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.GET_BROWSER_LIST}`, requestBody);
795
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_BROWSER_LIST}`, requestBody);
264
796
  if (response.data.code === 0) {
265
797
  return `Browser list: ${JSON.stringify(response.data.data.list, null, 2)}`;
266
798
  }
267
799
  throw new Error(`Failed to get browser list: ${response.data.msg}`);
268
800
  },
269
801
  async getOpenedBrowser() {
270
- const response = await apiClient.get(`${LOCAL_API_BASE}${API_ENDPOINTS.GET_OPENED_BROWSER}`);
802
+ const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_OPENED_BROWSER}`);
271
803
  if (response.data.code === 0) {
272
804
  return `Opened browser list: ${JSON.stringify(response.data.data.list, null, 2)}`;
273
805
  }
274
806
  throw new Error(`Failed to get opened browsers: ${response.data.msg}`);
275
807
  },
276
808
  async moveBrowser({ groupId, userIds }) {
277
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.MOVE_BROWSER}`, {
809
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.MOVE_BROWSER}`, {
278
810
  group_id: groupId,
279
811
  user_ids: userIds
280
812
  });
@@ -291,7 +823,7 @@ var browserHandlers = {
291
823
  if (profileNo) {
292
824
  params.set("profile_no", profileNo);
293
825
  }
294
- const response = await apiClient.get(`${LOCAL_API_BASE}${API_ENDPOINTS.GET_PROFILE_COOKIES}`, { params });
826
+ const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_PROFILE_COOKIES}`, { params });
295
827
  if (response.data.code === 0) {
296
828
  return `Profile cookies: ${JSON.stringify(response.data.data, null, 2)}`;
297
829
  }
@@ -305,14 +837,14 @@ var browserHandlers = {
305
837
  if (profileNo && profileNo.length > 0) {
306
838
  requestBody.profile_no = profileNo;
307
839
  }
308
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.GET_PROFILE_UA}`, requestBody);
840
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_PROFILE_UA}`, requestBody);
309
841
  if (response.data.code === 0) {
310
842
  return `Profile User-Agent: ${JSON.stringify(response.data.data, null, 2)}`;
311
843
  }
312
844
  throw new Error(`Failed to get profile User-Agent: ${response.data.msg}`);
313
845
  },
314
846
  async closeAllProfiles(_params) {
315
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.CLOSE_ALL_PROFILES}`, {});
847
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CLOSE_ALL_PROFILES}`, {});
316
848
  if (response.data.code === 0) {
317
849
  return "All profiles closed successfully";
318
850
  }
@@ -326,14 +858,14 @@ var browserHandlers = {
326
858
  if (profileNo && profileNo.length > 0) {
327
859
  requestBody.profile_no = profileNo;
328
860
  }
329
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.NEW_FINGERPRINT}`, requestBody);
861
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.NEW_FINGERPRINT}`, requestBody);
330
862
  if (response.data.code === 0) {
331
863
  return `New fingerprint created: ${JSON.stringify(response.data.data, null, 2)}`;
332
864
  }
333
865
  throw new Error(`Failed to create new fingerprint: ${response.data.msg}`);
334
866
  },
335
867
  async deleteCacheV2({ profileIds, type }) {
336
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.DELETE_CACHE_V2}`, {
868
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.DELETE_CACHE_V2}`, {
337
869
  profile_id: profileIds,
338
870
  type
339
871
  });
@@ -353,7 +885,7 @@ var browserHandlers = {
353
885
  if (content !== void 0) {
354
886
  requestBody.content = content;
355
887
  }
356
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.SHARE_PROFILE}`, requestBody);
888
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.SHARE_PROFILE}`, requestBody);
357
889
  if (response.data.code === 0) {
358
890
  return `Profiles shared successfully: ${profileIds.join(", ")}`;
359
891
  }
@@ -367,14 +899,14 @@ var browserHandlers = {
367
899
  if (profileNo) {
368
900
  params.set("profile_no", profileNo);
369
901
  }
370
- const response = await apiClient.get(`${LOCAL_API_BASE}${API_ENDPOINTS.GET_BROWSER_ACTIVE}`, { params });
902
+ const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_BROWSER_ACTIVE}`, { params });
371
903
  if (response.data.code === 0) {
372
904
  return `Browser active info: ${JSON.stringify(response.data.data, null, 2)}`;
373
905
  }
374
906
  throw new Error(`Failed to get browser active: ${response.data.msg}`);
375
907
  },
376
908
  async getCloudActive({ userIds }) {
377
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.GET_CLOUD_ACTIVE}`, {
909
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_CLOUD_ACTIVE}`, {
378
910
  user_ids: userIds
379
911
  });
380
912
  if (response.data.code === 0) {
@@ -393,7 +925,7 @@ var groupHandlers = {
393
925
  if (remark !== void 0) {
394
926
  requestBody.remark = remark;
395
927
  }
396
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.CREATE_GROUP}`, requestBody);
928
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CREATE_GROUP}`, requestBody);
397
929
  if (response.data.code === 0) {
398
930
  return `Group created successfully with name: ${groupName}${remark ? `, remark: ${remark}` : ""}`;
399
931
  }
@@ -407,7 +939,7 @@ var groupHandlers = {
407
939
  if (remark !== void 0) {
408
940
  requestBody.remark = remark;
409
941
  }
410
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.UPDATE_GROUP}`, requestBody);
942
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_GROUP}`, requestBody);
411
943
  if (response.data.code === 0) {
412
944
  return `Group updated successfully with id: ${groupId}, name: ${groupName}${remark !== void 0 ? `, remark: ${remark === null ? "(cleared)" : remark}` : ""}`;
413
945
  }
@@ -424,7 +956,7 @@ var groupHandlers = {
424
956
  if (page) {
425
957
  params.set("page", page.toString());
426
958
  }
427
- const response = await apiClient.get(`${LOCAL_API_BASE}${API_ENDPOINTS.GET_GROUP_LIST}`, { params });
959
+ const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_GROUP_LIST}`, { params });
428
960
  return `Group list: ${JSON.stringify(response.data.data.list, null, 2)}`;
429
961
  }
430
962
  };
@@ -432,7 +964,7 @@ var groupHandlers = {
432
964
  // ../core/src/handlers/application.ts
433
965
  var applicationHandlers = {
434
966
  async checkStatus() {
435
- const response = await apiClient.get(`${LOCAL_API_BASE}${API_ENDPOINTS.STATUS}`);
967
+ const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.STATUS}`);
436
968
  return `Connection status: ${JSON.stringify(response.data, null, 2)}`;
437
969
  },
438
970
  async getApplicationList({ category_id, page, limit }) {
@@ -446,7 +978,7 @@ var applicationHandlers = {
446
978
  if (limit !== void 0) {
447
979
  params.set("limit", limit.toString());
448
980
  }
449
- const response = await apiClient.get(`${LOCAL_API_BASE}${API_ENDPOINTS.GET_APPLICATION_LIST}`, { params });
981
+ const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_APPLICATION_LIST}`, { params });
450
982
  return `Application list: ${JSON.stringify(response.data.data.list, null, 2)}`;
451
983
  }
452
984
  };
@@ -508,7 +1040,7 @@ function buildCreateProxyRequestBody(proxy) {
508
1040
  var proxyHandlers = {
509
1041
  async createProxy(params) {
510
1042
  const requestBody = params.proxies.map((proxy) => buildCreateProxyRequestBody(proxy));
511
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.CREATE_PROXY}`, requestBody);
1043
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CREATE_PROXY}`, requestBody);
512
1044
  if (response.data.code === 0) {
513
1045
  return `Proxy created successfully with: ${Object.entries(response.data.data || {}).map(([key, value]) => `${key}: ${value}`).join("\n")}`;
514
1046
  }
@@ -516,7 +1048,7 @@ var proxyHandlers = {
516
1048
  },
517
1049
  async updateProxy(params) {
518
1050
  const requestBody = buildProxyRequestBody(params);
519
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.UPDATE_PROXY}`, requestBody);
1051
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_PROXY}`, requestBody);
520
1052
  if (response.data.code === 0) {
521
1053
  return `Proxy updated successfully with: ${Object.entries(response.data.data || {}).map(([key, value]) => `${key}: ${value}`).join("\n")}`;
522
1054
  }
@@ -534,14 +1066,14 @@ var proxyHandlers = {
534
1066
  if (proxyId && proxyId.length > 0) {
535
1067
  requestBody.proxy_id = proxyId;
536
1068
  }
537
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.GET_PROXY_LIST}`, requestBody);
1069
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_PROXY_LIST}`, requestBody);
538
1070
  if (response.data.code === 0) {
539
1071
  return `Proxy list: ${JSON.stringify(response.data.data.list || response.data.data, null, 2)}`;
540
1072
  }
541
1073
  throw new Error(`Failed to get proxy list: ${response.data.msg}`);
542
1074
  },
543
1075
  async deleteProxy({ proxyIds }) {
544
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.DELETE_PROXY}`, {
1076
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.DELETE_PROXY}`, {
545
1077
  proxy_id: proxyIds
546
1078
  });
547
1079
  if (response.data.code === 0) {
@@ -565,28 +1097,28 @@ var tagHandlers = {
565
1097
  if (page !== void 0) {
566
1098
  requestBody.page = page;
567
1099
  }
568
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.GET_TAG_LIST}`, requestBody);
1100
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_TAG_LIST}`, requestBody);
569
1101
  if (response.data.code === 0) {
570
1102
  return `Tag list: ${JSON.stringify(response.data.data.list || response.data.data, null, 2)}`;
571
1103
  }
572
1104
  throw new Error(`Failed to get tag list: ${response.data.msg}`);
573
1105
  },
574
1106
  async createTag({ tags }) {
575
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.CREATE_TAG}`, { tags });
1107
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CREATE_TAG}`, { tags });
576
1108
  if (response.data.code === 0) {
577
1109
  return `Tags created successfully: ${JSON.stringify(response.data.data, null, 2)}`;
578
1110
  }
579
1111
  throw new Error(`Failed to create tags: ${response.data.msg}`);
580
1112
  },
581
1113
  async updateTag({ tags }) {
582
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.UPDATE_TAG}`, { tags });
1114
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_TAG}`, { tags });
583
1115
  if (response.data.code === 0) {
584
1116
  return `Tags updated successfully: ${JSON.stringify(response.data.data, null, 2)}`;
585
1117
  }
586
1118
  throw new Error(`Failed to update tags: ${response.data.msg}`);
587
1119
  },
588
1120
  async deleteTag({ ids }) {
589
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.DELETE_TAG}`, { ids });
1121
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.DELETE_TAG}`, { ids });
590
1122
  if (response.data.code === 0) {
591
1123
  return `Tags deleted successfully: ${ids.join(", ")}`;
592
1124
  }
@@ -654,7 +1186,7 @@ var defaultDownloadsPath = import_path.default.join(import_os.default.homedir(),
654
1186
  // ../core/src/handlers/kernel.ts
655
1187
  var kernelHandlers = {
656
1188
  async downloadKernel({ kernel_type, kernel_version }) {
657
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.DOWNLOAD_KERNEL}`, {
1189
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.DOWNLOAD_KERNEL}`, {
658
1190
  kernel_type,
659
1191
  kernel_version
660
1192
  });
@@ -668,7 +1200,7 @@ var kernelHandlers = {
668
1200
  if (kernel_type) {
669
1201
  params.set("kernel_type", kernel_type);
670
1202
  }
671
- const response = await apiClient.get(`${LOCAL_API_BASE}${API_ENDPOINTS.GET_KERNEL_LIST}`, { params });
1203
+ const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_KERNEL_LIST}`, { params });
672
1204
  if (response.data.code === 0) {
673
1205
  return `Kernel list: ${JSON.stringify(response.data.data.list || response.data.data, null, 2)}`;
674
1206
  }
@@ -683,7 +1215,7 @@ var patchHandlers = {
683
1215
  if (version_type) {
684
1216
  requestBody.version_type = version_type;
685
1217
  }
686
- const response = await apiClient.post(`${LOCAL_API_BASE}${API_ENDPOINTS.UPDATE_PATCH}`, requestBody);
1218
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_PATCH}`, requestBody);
687
1219
  if (response.data.code === 0) {
688
1220
  return `Patch update status: ${JSON.stringify(response.data.data, null, 2)}, message: ${response.data.msg}`;
689
1221
  }
@@ -1420,38 +1952,134 @@ var schemas = {
1420
1952
 
1421
1953
  // src/cli.ts
1422
1954
  var STATELESS_HANDLERS = {
1423
- "open-browser": browserHandlers.openBrowser,
1424
- "close-browser": browserHandlers.closeBrowser,
1425
- "create-browser": browserHandlers.createBrowser,
1426
- "update-browser": browserHandlers.updateBrowser,
1427
- "delete-browser": browserHandlers.deleteBrowser,
1428
- "get-browser-list": browserHandlers.getBrowserList,
1429
- "get-opened-browser": browserHandlers.getOpenedBrowser,
1430
- "move-browser": browserHandlers.moveBrowser,
1431
- "get-profile-cookies": browserHandlers.getProfileCookies,
1432
- "get-profile-ua": browserHandlers.getProfileUa,
1433
- "close-all-profiles": browserHandlers.closeAllProfiles,
1434
- "new-fingerprint": browserHandlers.newFingerprint,
1435
- "delete-cache-v2": browserHandlers.deleteCacheV2,
1436
- "share-profile": browserHandlers.shareProfile,
1437
- "get-browser-active": browserHandlers.getBrowserActive,
1438
- "get-cloud-active": browserHandlers.getCloudActive,
1439
- "create-group": groupHandlers.createGroup,
1440
- "update-group": groupHandlers.updateGroup,
1441
- "get-group-list": groupHandlers.getGroupList,
1442
- "check-status": applicationHandlers.checkStatus,
1443
- "get-application-list": applicationHandlers.getApplicationList,
1444
- "create-proxy": proxyHandlers.createProxy,
1445
- "update-proxy": proxyHandlers.updateProxy,
1446
- "get-proxy-list": proxyHandlers.getProxyList,
1447
- "delete-proxy": proxyHandlers.deleteProxy,
1448
- "get-tag-list": tagHandlers.getTagList,
1449
- "create-tag": tagHandlers.createTag,
1450
- "update-tag": tagHandlers.updateTag,
1451
- "delete-tag": tagHandlers.deleteTag,
1452
- "download-kernel": kernelHandlers.downloadKernel,
1453
- "get-kernel-list": kernelHandlers.getKernelList,
1454
- "update-patch": patchHandlers.updatePatch
1955
+ "open-browser": {
1956
+ fn: browserHandlers.openBrowser,
1957
+ description: "Open the browser, both environment and profile mean browser"
1958
+ },
1959
+ "close-browser": {
1960
+ fn: browserHandlers.closeBrowser,
1961
+ description: "Close the browser"
1962
+ },
1963
+ "create-browser": {
1964
+ fn: browserHandlers.createBrowser,
1965
+ description: "Create a browser"
1966
+ },
1967
+ "update-browser": {
1968
+ fn: browserHandlers.updateBrowser,
1969
+ description: "Update the browser"
1970
+ },
1971
+ "delete-browser": {
1972
+ fn: browserHandlers.deleteBrowser,
1973
+ description: "Delete the browser"
1974
+ },
1975
+ "get-browser-list": {
1976
+ fn: browserHandlers.getBrowserList,
1977
+ description: "Get the list of browsers"
1978
+ },
1979
+ "get-opened-browser": {
1980
+ fn: browserHandlers.getOpenedBrowser,
1981
+ description: "Get the list of opened browsers"
1982
+ },
1983
+ "move-browser": {
1984
+ fn: browserHandlers.moveBrowser,
1985
+ description: "Move browsers to a group"
1986
+ },
1987
+ "get-profile-cookies": {
1988
+ fn: browserHandlers.getProfileCookies,
1989
+ description: "Query and return cookies of the specified profile. Only one profile can be queried per request."
1990
+ },
1991
+ "get-profile-ua": {
1992
+ fn: browserHandlers.getProfileUa,
1993
+ description: "Query and return the User-Agent of specified profiles. Up to 10 profiles can be queried per request."
1994
+ },
1995
+ "close-all-profiles": {
1996
+ fn: browserHandlers.closeAllProfiles,
1997
+ description: "Close all opened profiles on the current device"
1998
+ },
1999
+ "new-fingerprint": {
2000
+ fn: browserHandlers.newFingerprint,
2001
+ description: "Generate a new fingerprint for specified profiles. Up to 10 profiles are supported per request."
2002
+ },
2003
+ "delete-cache-v2": {
2004
+ fn: browserHandlers.deleteCacheV2,
2005
+ description: "Clear local cache of specific profiles.For account security, please ensure that there are no open browsers on the device when using this interface."
2006
+ },
2007
+ "share-profile": {
2008
+ fn: browserHandlers.shareProfile,
2009
+ description: "Share profiles via account email or phone number. The maximum number of profiles that can be shared at one time is 200."
2010
+ },
2011
+ "get-browser-active": {
2012
+ fn: browserHandlers.getBrowserActive,
2013
+ description: "Get active browser profile information"
2014
+ },
2015
+ "get-cloud-active": {
2016
+ fn: browserHandlers.getCloudActive,
2017
+ description: 'Query the status of browser profiles by user_id, 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."'
2018
+ },
2019
+ "create-group": {
2020
+ fn: groupHandlers.createGroup,
2021
+ description: "Create a browser group"
2022
+ },
2023
+ "update-group": {
2024
+ fn: groupHandlers.updateGroup,
2025
+ description: "Update the browser group"
2026
+ },
2027
+ "get-group-list": {
2028
+ fn: groupHandlers.getGroupList,
2029
+ description: "Get the list of groups"
2030
+ },
2031
+ "check-status": {
2032
+ fn: applicationHandlers.checkStatus,
2033
+ description: "Check the availability of the current device API interface (Connection Status)"
2034
+ },
2035
+ "get-application-list": {
2036
+ fn: applicationHandlers.getApplicationList,
2037
+ description: "Get the list of applications (categories)"
2038
+ },
2039
+ "create-proxy": {
2040
+ fn: proxyHandlers.createProxy,
2041
+ description: "Create the proxy"
2042
+ },
2043
+ "update-proxy": {
2044
+ fn: proxyHandlers.updateProxy,
2045
+ description: "Update the proxy"
2046
+ },
2047
+ "get-proxy-list": {
2048
+ fn: proxyHandlers.getProxyList,
2049
+ description: "Get the list of proxies"
2050
+ },
2051
+ "delete-proxy": {
2052
+ fn: proxyHandlers.deleteProxy,
2053
+ description: "Delete the proxy"
2054
+ },
2055
+ "get-tag-list": {
2056
+ fn: tagHandlers.getTagList,
2057
+ description: "Get the list of browser tags"
2058
+ },
2059
+ "create-tag": {
2060
+ fn: tagHandlers.createTag,
2061
+ description: "Create browser tags (batch supported)"
2062
+ },
2063
+ "update-tag": {
2064
+ fn: tagHandlers.updateTag,
2065
+ description: "Update browser tags (batch supported)"
2066
+ },
2067
+ "delete-tag": {
2068
+ fn: tagHandlers.deleteTag,
2069
+ description: "Delete browser tags"
2070
+ },
2071
+ "download-kernel": {
2072
+ fn: kernelHandlers.downloadKernel,
2073
+ description: "Download or update a browser kernel version"
2074
+ },
2075
+ "get-kernel-list": {
2076
+ fn: kernelHandlers.getKernelList,
2077
+ description: "Get browser kernel list by type or all"
2078
+ },
2079
+ "update-patch": {
2080
+ fn: patchHandlers.updatePatch,
2081
+ description: "Update AdsPower to latest patch version"
2082
+ }
1455
2083
  };
1456
2084
  var SINGLE_PROFILE_ID_COMMANDS = {
1457
2085
  "open-browser": "profileId",
@@ -1460,56 +2088,109 @@ var SINGLE_PROFILE_ID_COMMANDS = {
1460
2088
  "get-browser-active": "profileId"
1461
2089
  };
1462
2090
  var SINGLE_PROFILE_ID_ARRAY_COMMANDS = ["get-profile-ua", "new-fingerprint"];
1463
- function parseArgv(argv) {
1464
- let i = 0;
1465
- while (i < argv.length) {
1466
- if (argv[i] === "--port" || argv[i] === "--api-key") {
1467
- i += 2;
1468
- continue;
1469
- }
1470
- break;
1471
- }
1472
- const command = argv[i];
1473
- const arg = argv[i + 1];
1474
- if (!command || !STATELESS_HANDLERS[command]) {
1475
- throw new Error(`Unknown or unsupported command: ${command || "(missing)"}. Supported: ${Object.keys(STATELESS_HANDLERS).join(", ")}`);
1476
- }
1477
- let args = {};
1478
- if (arg) {
1479
- const trimmed = arg.trim();
1480
- if (trimmed.startsWith("{")) {
1481
- try {
1482
- args = JSON.parse(arg);
1483
- } catch {
1484
- throw new Error("Invalid JSON for command args");
2091
+
2092
+ // src/index.ts
2093
+ var program = new import_commander.Command();
2094
+ program.name("adspower-browser").description("CLI and runtime for adspower-browser").version(VERSION);
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) => {
2096
+ if (options.apiKey) {
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", "");
2105
+ }
2106
+ if (options.baseUrl) {
2107
+ store.setStoreValue("baseUrl", options.baseUrl);
2108
+ }
2109
+ if (options.nodeEnv) {
2110
+ store.setStoreValue("nodeEnv", options.nodeEnv);
2111
+ }
2112
+ await startChild();
2113
+ });
2114
+ program.command("stop").description("Stop the adspower runtime").action(async () => {
2115
+ await stopChild();
2116
+ });
2117
+ program.command("restart").description("Restart the adspower runtime").action(async () => {
2118
+ await restartChild();
2119
+ });
2120
+ program.command("status").description("Get the status of the adspower runtime").action(async () => {
2121
+ getChildStatus();
2122
+ });
2123
+ for (const cmd of Object.keys(STATELESS_HANDLERS)) {
2124
+ const fnc = STATELESS_HANDLERS[cmd].fn;
2125
+ 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) => {
2126
+ const isRun = await hasRunning(options);
2127
+ if (!isRun) {
2128
+ logError("[!] Adspower runtime is not running");
2129
+ const info = `[i] Please run "${(0, import_colors2.green)("adspower-browser start -k <apiKey>")}" to start the adspower runtime`;
2130
+ console.log(info);
2131
+ return;
2132
+ }
2133
+ const { apiKey, port } = getApiKeyAndPort(options);
2134
+ updateConfig(apiKey, port);
2135
+ let args = {};
2136
+ if (params) {
2137
+ const trimmed = params.trim();
2138
+ if (trimmed.startsWith("{")) {
2139
+ try {
2140
+ args = JSON.parse(params);
2141
+ } catch {
2142
+ logError("Invalid JSON for command args");
2143
+ return;
2144
+ }
2145
+ } else if (SINGLE_PROFILE_ID_COMMANDS[command.name()]) {
2146
+ const key = SINGLE_PROFILE_ID_COMMANDS[command.name()];
2147
+ if (!isNaN(Number(trimmed))) {
2148
+ args = { profileNo: Number(trimmed) };
2149
+ } else {
2150
+ args = { profileId: trimmed };
2151
+ }
2152
+ } else if (SINGLE_PROFILE_ID_ARRAY_COMMANDS.includes(command.name())) {
2153
+ args = { profileId: [trimmed] };
2154
+ } else {
2155
+ try {
2156
+ args = JSON.parse(params);
2157
+ } catch {
2158
+ logError(`Command requires JSON args (e.g. '{"key":"value"}') or use a supported shorthand`);
2159
+ return;
2160
+ }
1485
2161
  }
1486
- } else if (SINGLE_PROFILE_ID_COMMANDS[command]) {
1487
- const key = SINGLE_PROFILE_ID_COMMANDS[command];
1488
- args = { [key]: trimmed };
1489
- } else if (SINGLE_PROFILE_ID_ARRAY_COMMANDS.includes(command)) {
1490
- args = { profileId: [trimmed] };
1491
- } else {
1492
- try {
1493
- args = JSON.parse(arg);
1494
- } catch {
1495
- throw new Error(`Command requires JSON args (e.g. '{"key":"value"}') or use a supported shorthand`);
2162
+ }
2163
+ logSuccess(`Executing command: ${command.name()}, params: ${JSON.stringify(args)}`);
2164
+ const loading = createLoading(`Executing ${command.name()}...`);
2165
+ try {
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(`
2179
+
2180
+ ${out}
2181
+ `);
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
+ }
1496
2187
  }
2188
+ } finally {
2189
+ loading.stop();
1497
2190
  }
1498
- }
1499
- return { command, args };
1500
- }
1501
- async function main() {
1502
- const argv = process.argv.slice(2);
1503
- try {
1504
- const { command, args } = parseArgv(argv);
1505
- const handler = STATELESS_HANDLERS[command];
1506
- const result = await handler(args);
1507
- const out = typeof result === "string" ? result : JSON.stringify(result, null, 2);
1508
- process.stdout.write(out + "\n");
1509
- } catch (err) {
1510
- const msg = err instanceof Error ? err.message : String(err);
1511
- process.stderr.write(msg + "\n");
1512
- process.exit(1);
1513
- }
2191
+ });
1514
2192
  }
1515
- main();
2193
+ program.parseAsync(process.argv).catch((error) => {
2194
+ console.error(error);
2195
+ process.exit(1);
2196
+ });