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

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/cli/index.js CHANGED
@@ -106,6 +106,10 @@ 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
108
  var VERSION = "1.0.0";
109
+ var toTerminalLink = (url, label) => {
110
+ const text = label || url;
111
+ return `\x1B]8;;${url}\x07${text}\x1B]8;;\x07`;
112
+ };
109
113
  var logError = (message) => {
110
114
  console.error((0, import_colors.red)(message));
111
115
  };
@@ -355,11 +359,14 @@ var startChild = (type) => {
355
359
  );
356
360
  try {
357
361
  const mainJs = path2.join(__dirname, "../cwd/lib", "main.min.js");
358
- child = (0, import_node_child_process2.fork)(mainJs, {
362
+ const forkOptions = {
359
363
  env,
360
364
  detached: true,
365
+ windowsHide: true,
366
+ // 隐藏子进程的控制台窗口
361
367
  stdio: ["ignore", "ignore", "ignore", "ipc"]
362
- });
368
+ };
369
+ child = (0, import_node_child_process2.fork)(mainJs, [], forkOptions);
363
370
  ensureBrowserPath();
364
371
  store.setStoreValue("status", "starting");
365
372
  logSuccess(`[i] Adspower program is starting...`);
@@ -376,14 +383,19 @@ var startChild = (type) => {
376
383
  if (text.indexOf("START_API_SERVER_SUCCESS_$$_") === 0) {
377
384
  const port = text.replace("START_API_SERVER_SUCCESS_$$_", "").trim();
378
385
  store.setStoreValue("apiPort", port);
386
+ const localUrl = `http://local.adspower.net:${port}`;
379
387
  logSuccess(`Server running at:`);
380
- logSuccess(` - local: http://local.adspower.net:${port}`);
388
+ logSuccess(` - local: ${toTerminalLink(localUrl)}`);
381
389
  writePidFile(store.getAllStoreValue());
382
390
  if (child) {
383
391
  child.disconnect();
384
392
  child.unref();
385
393
  }
386
394
  }
395
+ if (text.includes("CACHE_FOLDER_$$_")) {
396
+ const cacheFolder = text.replace("CACHE_FOLDER_$$_", "").trim();
397
+ logSuccess(`[i] Cache folder: ${cacheFolder}`);
398
+ }
387
399
  if (text.indexOf("START_API_SERVER_FAIL_$$_") === 0) {
388
400
  const serverMsg = text.replace("START_API_SERVER_FAIL_$$_", "").split("_").filter(Boolean);
389
401
  if (serverMsg[0]) {
@@ -572,106 +584,772 @@ var PORT = config.port;
572
584
  var API_KEY = config.apiKey;
573
585
  var CONFIG = config;
574
586
 
587
+ // ../core/src/constants/localApiContracts.ts
588
+ var LOCAL_API_CONTRACTS = {
589
+ "check-status": {
590
+ method: "GET",
591
+ path: "/status",
592
+ params: {}
593
+ },
594
+ "get-application-list": {
595
+ method: "GET",
596
+ path: "/api/v2/category/list",
597
+ params: {
598
+ category_id: { apiName: "category_id", location: "query" },
599
+ page: { apiName: "page", location: "query" },
600
+ limit: { apiName: "limit", location: "query" }
601
+ }
602
+ },
603
+ "open-browser": {
604
+ method: "POST",
605
+ path: "/api/v2/browser-profile/start",
606
+ params: {
607
+ profile_id: { apiName: "profile_id", location: "body" },
608
+ profile_no: { apiName: "profile_no", location: "body" },
609
+ ip_tab: { apiName: "ip_tab", location: "body" },
610
+ launch_args: { apiName: "launch_args", location: "body" },
611
+ headless: { apiName: "headless", location: "body" },
612
+ last_opened_tabs: { apiName: "last_opened_tabs", location: "body" },
613
+ proxy_detection: { apiName: "proxy_detection", location: "body" },
614
+ password_filling: { apiName: "password_filling", location: "body" },
615
+ password_saving: { apiName: "password_saving", location: "body" },
616
+ cdp_mask: { apiName: "cdp_mask", location: "body" },
617
+ delete_cache: { apiName: "delete_cache", location: "body" },
618
+ device_scale: { apiName: "device_scale", location: "body" }
619
+ }
620
+ },
621
+ "close-browser": {
622
+ method: "POST",
623
+ path: "/api/v2/browser-profile/stop",
624
+ params: {
625
+ profile_id: { apiName: "profile_id", location: "body" },
626
+ profile_no: { apiName: "profile_no", location: "body" }
627
+ }
628
+ },
629
+ "create-browser": {
630
+ method: "POST",
631
+ path: "/api/v2/browser-profile/create",
632
+ params: {
633
+ group_id: { apiName: "group_id", location: "body" },
634
+ username: { apiName: "username", location: "body" },
635
+ password: { apiName: "password", location: "body" },
636
+ cookie: { apiName: "cookie", location: "body" },
637
+ fakey: { apiName: "fakey", location: "body" },
638
+ name: { apiName: "name", location: "body" },
639
+ platform: { apiName: "platform", location: "body" },
640
+ remark: { apiName: "remark", location: "body" },
641
+ user_proxy_config: { apiName: "user_proxy_config", location: "body" },
642
+ proxyid: { apiName: "proxyid", location: "body" },
643
+ repeat_config: { apiName: "repeat_config", location: "body" },
644
+ ignore_cookie_error: { apiName: "ignore_cookie_error", location: "body" },
645
+ tabs: { apiName: "tabs", location: "body" },
646
+ ip: { apiName: "ip", location: "body" },
647
+ country: { apiName: "country", location: "body" },
648
+ region: { apiName: "region", location: "body" },
649
+ city: { apiName: "city", location: "body" },
650
+ ipchecker: { apiName: "ipchecker", location: "body" },
651
+ category_id: { apiName: "category_id", location: "body" },
652
+ profile_tag_ids: { apiName: "profile_tag_ids", location: "body" },
653
+ fingerprint_config: { apiName: "fingerprint_config", location: "body" },
654
+ platform_account: { apiName: "platform_account", location: "body" }
655
+ }
656
+ },
657
+ "update-browser": {
658
+ method: "POST",
659
+ path: "/api/v2/browser-profile/update",
660
+ params: {
661
+ profile_id: { apiName: "profile_id", location: "body" },
662
+ group_id: { apiName: "group_id", location: "body" },
663
+ username: { apiName: "username", location: "body" },
664
+ password: { apiName: "password", location: "body" },
665
+ cookie: { apiName: "cookie", location: "body" },
666
+ fakey: { apiName: "fakey", location: "body" },
667
+ name: { apiName: "name", location: "body" },
668
+ platform: { apiName: "platform", location: "body" },
669
+ remark: { apiName: "remark", location: "body" },
670
+ user_proxy_config: { apiName: "user_proxy_config", location: "body" },
671
+ proxyid: { apiName: "proxyid", location: "body" },
672
+ repeat_config: { apiName: "repeat_config", location: "body" },
673
+ ignore_cookie_error: { apiName: "ignore_cookie_error", location: "body" },
674
+ tabs: { apiName: "tabs", location: "body" },
675
+ ip: { apiName: "ip", location: "body" },
676
+ country: { apiName: "country", location: "body" },
677
+ region: { apiName: "region", location: "body" },
678
+ city: { apiName: "city", location: "body" },
679
+ ipchecker: { apiName: "ipchecker", location: "body" },
680
+ category_id: { apiName: "category_id", location: "body" },
681
+ profile_tag_ids: { apiName: "profile_tag_ids", location: "body" },
682
+ fingerprint_config: { apiName: "fingerprint_config", location: "body" },
683
+ platform_account: { apiName: "platform_account", location: "body" },
684
+ launch_args: { apiName: "launch_args", location: "body" },
685
+ tags_update_type: { apiName: "tags_update_type", location: "body" }
686
+ }
687
+ },
688
+ "delete-browser": {
689
+ method: "POST",
690
+ path: "/api/v2/browser-profile/delete",
691
+ params: {
692
+ profile_id: { apiName: "profile_id", location: "body" }
693
+ }
694
+ },
695
+ "get-browser-list": {
696
+ method: "POST",
697
+ path: "/api/v2/browser-profile/list",
698
+ params: {
699
+ group_id: { apiName: "group_id", location: "body" },
700
+ limit: { apiName: "limit", location: "body" },
701
+ page: { apiName: "page", location: "body" },
702
+ profile_id: { apiName: "profile_id", location: "body" },
703
+ profile_no: { apiName: "profile_no", location: "body" },
704
+ sort_type: { apiName: "sort_type", location: "body" },
705
+ sort_order: { apiName: "sort_order", location: "body" },
706
+ tag_ids: { apiName: "tag_ids", location: "body" },
707
+ tags_filter: { apiName: "tags_filter", location: "body" },
708
+ name: { apiName: "name", location: "body" },
709
+ name_filter: { apiName: "name_filter", location: "body" }
710
+ }
711
+ },
712
+ "get-opened-browser": {
713
+ method: "GET",
714
+ path: "/api/v1/browser/local-active",
715
+ params: {}
716
+ },
717
+ "move-browser": {
718
+ method: "POST",
719
+ path: "/api/v1/user/regroup",
720
+ params: {
721
+ user_ids: { apiName: "user_ids", location: "body" },
722
+ group_id: { apiName: "group_id", location: "body" }
723
+ }
724
+ },
725
+ "get-profile-cookies": {
726
+ method: "GET",
727
+ path: "/api/v2/browser-profile/cookies",
728
+ params: {
729
+ profile_id: { apiName: "profile_id", location: "query" },
730
+ profile_no: { apiName: "profile_no", location: "query" }
731
+ }
732
+ },
733
+ "get-profile-ua": {
734
+ method: "POST",
735
+ path: "/api/v2/browser-profile/ua",
736
+ params: {
737
+ profile_id: { apiName: "profile_id", location: "body" },
738
+ profile_no: { apiName: "profile_no", location: "body" }
739
+ }
740
+ },
741
+ "close-all-profiles": {
742
+ method: "POST",
743
+ path: "/api/v2/browser-profile/stop-all",
744
+ params: {}
745
+ },
746
+ "new-fingerprint": {
747
+ method: "POST",
748
+ path: "/api/v2/browser-profile/new-fingerprint",
749
+ params: {
750
+ profile_id: { apiName: "profile_id", location: "body" },
751
+ profile_no: { apiName: "profile_no", location: "body" }
752
+ }
753
+ },
754
+ "delete-cache-v2": {
755
+ method: "POST",
756
+ path: "/api/v2/browser-profile/delete-cache",
757
+ params: {
758
+ profile_id: { apiName: "profile_id", location: "body" },
759
+ type: { apiName: "type", location: "body" }
760
+ }
761
+ },
762
+ "share-profile": {
763
+ method: "POST",
764
+ path: "/api/v2/browser-profile/share",
765
+ params: {
766
+ profile_id: { apiName: "profile_id", location: "body" },
767
+ receiver: { apiName: "receiver", location: "body" },
768
+ share_type: { apiName: "share_type", location: "body" },
769
+ content: { apiName: "content", location: "body" }
770
+ }
771
+ },
772
+ "get-browser-active": {
773
+ method: "GET",
774
+ path: "/api/v2/browser-profile/active",
775
+ params: {
776
+ profile_id: { apiName: "profile_id", location: "query" },
777
+ profile_no: { apiName: "profile_no", location: "query" }
778
+ }
779
+ },
780
+ "get-cloud-active": {
781
+ method: "POST",
782
+ path: "/api/v1/browser/cloud-active",
783
+ params: {
784
+ user_ids: { apiName: "user_ids", location: "body" }
785
+ }
786
+ },
787
+ "create-group": {
788
+ method: "POST",
789
+ path: "/api/v1/group/create",
790
+ params: {
791
+ group_name: { apiName: "group_name", location: "body" },
792
+ remark: { apiName: "remark", location: "body" }
793
+ }
794
+ },
795
+ "update-group": {
796
+ method: "POST",
797
+ path: "/api/v1/group/update",
798
+ params: {
799
+ group_id: { apiName: "group_id", location: "body" },
800
+ group_name: { apiName: "group_name", location: "body" },
801
+ remark: { apiName: "remark", location: "body" }
802
+ }
803
+ },
804
+ "get-group-list": {
805
+ method: "GET",
806
+ path: "/api/v1/group/list",
807
+ params: {
808
+ group_name: { apiName: "group_name", location: "query" },
809
+ page: { apiName: "page", location: "query" },
810
+ page_size: { apiName: "page_size", location: "query" }
811
+ }
812
+ },
813
+ "create-proxy": {
814
+ method: "POST",
815
+ path: "/api/v2/proxy-list/create",
816
+ params: {},
817
+ bodyShape: "array"
818
+ },
819
+ "update-proxy": {
820
+ method: "POST",
821
+ path: "/api/v2/proxy-list/update",
822
+ params: {
823
+ proxy_id: { apiName: "proxy_id", location: "body" },
824
+ type: { apiName: "type", location: "body" },
825
+ host: { apiName: "host", location: "body" },
826
+ port: { apiName: "port", location: "body" },
827
+ user: { apiName: "user", location: "body" },
828
+ password: { apiName: "password", location: "body" },
829
+ proxy_url: { apiName: "proxy_url", location: "body" },
830
+ remark: { apiName: "remark", location: "body" },
831
+ ipchecker: { apiName: "ipchecker", location: "body" }
832
+ }
833
+ },
834
+ "get-proxy-list": {
835
+ method: "POST",
836
+ path: "/api/v2/proxy-list/list",
837
+ params: {
838
+ proxy_id: { apiName: "proxy_id", location: "body" },
839
+ limit: { apiName: "limit", location: "body" },
840
+ page: { apiName: "page", location: "body" }
841
+ }
842
+ },
843
+ "delete-proxy": {
844
+ method: "POST",
845
+ path: "/api/v2/proxy-list/delete",
846
+ params: {
847
+ proxy_id: { apiName: "proxy_id", location: "body" }
848
+ }
849
+ },
850
+ "get-tag-list": {
851
+ method: "POST",
852
+ path: "/api/v2/browser-tags/list",
853
+ params: {
854
+ ids: { apiName: "ids", location: "body" },
855
+ page: { apiName: "page", location: "body" },
856
+ limit: { apiName: "limit", location: "body" }
857
+ }
858
+ },
859
+ "create-tag": {
860
+ method: "POST",
861
+ path: "/api/v2/browser-tags/create",
862
+ params: {
863
+ tags: { apiName: "tags", location: "body" }
864
+ }
865
+ },
866
+ "update-tag": {
867
+ method: "POST",
868
+ path: "/api/v2/browser-tags/update",
869
+ params: {
870
+ tags: { apiName: "tags", location: "body" }
871
+ }
872
+ },
873
+ "delete-tag": {
874
+ method: "POST",
875
+ path: "/api/v2/browser-tags/delete",
876
+ params: {
877
+ ids: { apiName: "ids", location: "body" }
878
+ }
879
+ },
880
+ "download-kernel": {
881
+ method: "POST",
882
+ path: "/api/v2/browser-profile/download-kernel",
883
+ params: {
884
+ kernel_type: { apiName: "kernel_type", location: "body" },
885
+ kernel_version: { apiName: "kernel_version", location: "body" }
886
+ }
887
+ },
888
+ "get-kernel-list": {
889
+ method: "GET",
890
+ path: "/api/v2/browser-profile/kernels",
891
+ params: {
892
+ kernel_type: { apiName: "kernel_type", location: "query" }
893
+ }
894
+ },
895
+ "update-patch": {
896
+ method: "POST",
897
+ path: "/api/v2/browser-profile/update-patch",
898
+ params: {
899
+ version_type: { apiName: "version_type", location: "body" }
900
+ }
901
+ }
902
+ };
903
+
575
904
  // ../core/src/constants/api.ts
905
+ function readLocalApiMinIntervalMs() {
906
+ const raw = process.env.ADSP_LOCAL_API_MIN_INTERVAL_MS?.trim() ?? "";
907
+ if (!raw) {
908
+ return 0;
909
+ }
910
+ const n = Number(raw);
911
+ return Number.isFinite(n) && n > 0 ? Math.floor(n) : 0;
912
+ }
913
+ var localApiThrottleLock = Promise.resolve();
914
+ var localApiLastRequestStartMs = 0;
915
+ async function sleep(ms) {
916
+ await new Promise((resolve) => {
917
+ setTimeout(resolve, ms);
918
+ });
919
+ }
920
+ async function throttleLocalApiRequest() {
921
+ const gapMs = readLocalApiMinIntervalMs();
922
+ if (gapMs <= 0) {
923
+ return;
924
+ }
925
+ const prev = localApiThrottleLock;
926
+ let release;
927
+ localApiThrottleLock = new Promise((resolve) => {
928
+ release = resolve;
929
+ });
930
+ await prev;
931
+ try {
932
+ const now = Date.now();
933
+ const earliest = localApiLastRequestStartMs === 0 ? now : localApiLastRequestStartMs + gapMs;
934
+ const waitMs = Math.max(0, earliest - now);
935
+ if (waitMs > 0) {
936
+ await sleep(waitMs);
937
+ }
938
+ localApiLastRequestStartMs = Date.now();
939
+ } finally {
940
+ release();
941
+ }
942
+ }
943
+ function isLocalApiRequestUrl(url) {
944
+ if (!url) {
945
+ return false;
946
+ }
947
+ try {
948
+ const u = new URL(url, "http://127.0.0.1");
949
+ return u.hostname === "127.0.0.1" || u.hostname === "localhost";
950
+ } catch {
951
+ return url.includes("127.0.0.1") || url.includes("localhost");
952
+ }
953
+ }
576
954
  var LOCAL_API_BASE = `http://127.0.0.1:${PORT}`;
577
955
  var getLocalApiBase = () => {
578
956
  return `http://127.0.0.1:${CONFIG.port}`;
579
957
  };
580
958
  var API_ENDPOINTS = {
581
959
  STATUS: "/status",
582
- START_BROWSER: "/api/v2/browser-profile/start",
583
- CLOSE_BROWSER: "/api/v2/browser-profile/stop",
584
- CREATE_BROWSER: "/api/v2/browser-profile/create",
585
- GET_BROWSER_LIST: "/api/v2/browser-profile/list",
586
- UPDATE_BROWSER: "/api/v2/browser-profile/update",
587
- DELETE_BROWSER: "/api/v2/browser-profile/delete",
588
- GET_PROFILE_COOKIES: "/api/v2/browser-profile/cookies",
589
- GET_PROFILE_UA: "/api/v2/browser-profile/ua",
590
- CLOSE_ALL_PROFILES: "/api/v2/browser-profile/stop-all",
591
- NEW_FINGERPRINT: "/api/v2/browser-profile/new-fingerprint",
592
- DELETE_CACHE_V2: "/api/v2/browser-profile/delete-cache",
593
- SHARE_PROFILE: "/api/v2/browser-profile/share",
594
- GET_BROWSER_ACTIVE: "/api/v2/browser-profile/active",
595
- CREATE_PROXY: "/api/v2/proxy-list/create",
596
- UPDATE_PROXY: "/api/v2/proxy-list/update",
597
- GET_PROXY_LIST: "/api/v2/proxy-list/list",
598
- DELETE_PROXY: "/api/v2/proxy-list/delete",
599
- GET_OPENED_BROWSER: "/api/v1/browser/local-active",
600
- GET_CLOUD_ACTIVE: "/api/v1/browser/cloud-active",
601
- MOVE_BROWSER: "/api/v1/user/regroup",
602
- GET_GROUP_LIST: "/api/v1/group/list",
603
- CREATE_GROUP: "/api/v1/group/create",
604
- UPDATE_GROUP: "/api/v1/group/update",
605
- GET_APPLICATION_LIST: "/api/v2/category/list",
606
- GET_TAG_LIST: "/api/v2/browser-tags/list",
607
- CREATE_TAG: "/api/v2/browser-tags/create",
608
- UPDATE_TAG: "/api/v2/browser-tags/update",
609
- DELETE_TAG: "/api/v2/browser-tags/delete",
610
- DOWNLOAD_KERNEL: "/api/v2/browser-profile/download-kernel",
611
- GET_KERNEL_LIST: "/api/v2/browser-profile/kernels",
612
- UPDATE_PATCH: "/api/v2/browser-profile/update-patch"
960
+ START_BROWSER: LOCAL_API_CONTRACTS["open-browser"].path,
961
+ CLOSE_BROWSER: LOCAL_API_CONTRACTS["close-browser"].path,
962
+ CREATE_BROWSER: LOCAL_API_CONTRACTS["create-browser"].path,
963
+ GET_BROWSER_LIST: LOCAL_API_CONTRACTS["get-browser-list"].path,
964
+ UPDATE_BROWSER: LOCAL_API_CONTRACTS["update-browser"].path,
965
+ DELETE_BROWSER: LOCAL_API_CONTRACTS["delete-browser"].path,
966
+ GET_PROFILE_COOKIES: LOCAL_API_CONTRACTS["get-profile-cookies"].path,
967
+ GET_PROFILE_UA: LOCAL_API_CONTRACTS["get-profile-ua"].path,
968
+ CLOSE_ALL_PROFILES: LOCAL_API_CONTRACTS["close-all-profiles"].path,
969
+ NEW_FINGERPRINT: LOCAL_API_CONTRACTS["new-fingerprint"].path,
970
+ DELETE_CACHE_V2: LOCAL_API_CONTRACTS["delete-cache-v2"].path,
971
+ SHARE_PROFILE: LOCAL_API_CONTRACTS["share-profile"].path,
972
+ GET_BROWSER_ACTIVE: LOCAL_API_CONTRACTS["get-browser-active"].path,
973
+ CREATE_PROXY: LOCAL_API_CONTRACTS["create-proxy"].path,
974
+ UPDATE_PROXY: LOCAL_API_CONTRACTS["update-proxy"].path,
975
+ GET_PROXY_LIST: LOCAL_API_CONTRACTS["get-proxy-list"].path,
976
+ DELETE_PROXY: LOCAL_API_CONTRACTS["delete-proxy"].path,
977
+ GET_OPENED_BROWSER: LOCAL_API_CONTRACTS["get-opened-browser"].path,
978
+ GET_CLOUD_ACTIVE: LOCAL_API_CONTRACTS["get-cloud-active"].path,
979
+ MOVE_BROWSER: LOCAL_API_CONTRACTS["move-browser"].path,
980
+ GET_GROUP_LIST: LOCAL_API_CONTRACTS["get-group-list"].path,
981
+ CREATE_GROUP: LOCAL_API_CONTRACTS["create-group"].path,
982
+ UPDATE_GROUP: LOCAL_API_CONTRACTS["update-group"].path,
983
+ GET_APPLICATION_LIST: LOCAL_API_CONTRACTS["get-application-list"].path,
984
+ GET_TAG_LIST: LOCAL_API_CONTRACTS["get-tag-list"].path,
985
+ CREATE_TAG: LOCAL_API_CONTRACTS["create-tag"].path,
986
+ UPDATE_TAG: LOCAL_API_CONTRACTS["update-tag"].path,
987
+ DELETE_TAG: LOCAL_API_CONTRACTS["delete-tag"].path,
988
+ DOWNLOAD_KERNEL: LOCAL_API_CONTRACTS["download-kernel"].path,
989
+ GET_KERNEL_LIST: LOCAL_API_CONTRACTS["get-kernel-list"].path,
990
+ UPDATE_PATCH: LOCAL_API_CONTRACTS["update-patch"].path
613
991
  };
614
992
  var apiClient = import_axios.default.create({
615
993
  headers: API_KEY ? { "Authorization": `Bearer ${API_KEY}` } : {}
616
994
  });
617
995
  var getApiClient = () => {
618
- return import_axios.default.create({
996
+ const client = import_axios.default.create({
619
997
  headers: CONFIG.apiKey ? { "Authorization": `Bearer ${CONFIG.apiKey}` } : {}
620
998
  });
999
+ client.interceptors.request.use(async (config2) => {
1000
+ if (isLocalApiRequestUrl(config2.url)) {
1001
+ await throttleLocalApiRequest();
1002
+ }
1003
+ return config2;
1004
+ });
1005
+ return client;
621
1006
  };
622
1007
 
1008
+ // ../core/src/constants/toolIntentMetadata.ts
1009
+ var TOOL_INTENT_BY_NAME = {
1010
+ "open-browser": {
1011
+ intentEn: "Start an existing AdsPower browser profile (launch the profile browser).",
1012
+ intentZh: "\u542F\u52A8\u5DF2\u5B58\u5728\u7684 AdsPower \u6D4F\u89C8\u5668\u73AF\u5883\uFF08\u7528\u6237\u5E38\u79F0\u73AF\u5883\u3001\u914D\u7F6E\u6587\u4EF6\u3001profile\uFF09\u3002",
1013
+ triggersEn: "open browser, launch profile, start environment, open AdsPower, open config profile",
1014
+ triggersZh: "\u6253\u5F00\u6D4F\u89C8\u5668,\u542F\u52A8\u73AF\u5883,\u6253\u5F00\u914D\u7F6E,\u6253\u5F00\u914D\u7F6E\u6587\u4EF6,\u6253\u5F00profile,\u62C9\u8D77AdsPower,\u542F\u52A8\u6307\u7EB9\u6D4F\u89C8\u5668"
1015
+ },
1016
+ "close-browser": {
1017
+ intentEn: "Stop a running AdsPower browser profile.",
1018
+ intentZh: "\u5173\u95ED\u6B63\u5728\u8FD0\u884C\u7684\u6D4F\u89C8\u5668\u73AF\u5883 / profile\u3002",
1019
+ triggersEn: "close browser, stop profile, shutdown environment, kill browser",
1020
+ triggersZh: "\u5173\u95ED\u6D4F\u89C8\u5668,\u505C\u6B62\u73AF\u5883,\u5173\u6389profile,\u7ED3\u675F\u6D4F\u89C8\u5668,\u9000\u51FA\u6307\u7EB9\u73AF\u5883"
1021
+ },
1022
+ "create-browser": {
1023
+ intentEn: "Create a new AdsPower browser profile (account).",
1024
+ intentZh: "\u65B0\u5EFA\u6D4F\u89C8\u5668\u73AF\u5883 / \u8D26\u53F7 profile\u3002",
1025
+ triggersEn: "create profile, new browser, add account, spin up profile",
1026
+ triggersZh: "\u65B0\u5EFA\u73AF\u5883,\u521B\u5EFAprofile,\u6DFB\u52A0\u6D4F\u89C8\u5668,\u65B0\u5F00\u6307\u7EB9,\u521B\u5EFA\u8D26\u53F7"
1027
+ },
1028
+ "update-browser": {
1029
+ intentEn: "Update fields of an existing browser profile.",
1030
+ intentZh: "\u66F4\u65B0\u5DF2\u6709 profile \u7684\u914D\u7F6E\uFF08\u5907\u6CE8\u3001\u4EE3\u7406\u3001\u6307\u7EB9\u7B49\uFF09\u3002",
1031
+ triggersEn: "edit profile, change settings, modify browser, update fingerprint",
1032
+ triggersZh: "\u4FEE\u6539\u914D\u7F6E,\u66F4\u65B0profile,\u6539\u4EE3\u7406,\u6539\u6307\u7EB9,\u7F16\u8F91\u73AF\u5883"
1033
+ },
1034
+ "delete-browser": {
1035
+ intentEn: "Delete one or more browser profiles permanently.",
1036
+ intentZh: "\u6C38\u4E45\u5220\u9664\u4E00\u4E2A\u6216\u591A\u4E2A\u6D4F\u89C8\u5668 profile\u3002",
1037
+ triggersEn: "remove profile, delete account, trash browser",
1038
+ triggersZh: "\u5220\u9664\u73AF\u5883,\u79FB\u9664profile,\u5220\u6389\u6D4F\u89C8\u5668\u8D26\u53F7"
1039
+ },
1040
+ "get-browser-list": {
1041
+ intentEn: "List or search browser profiles (pagination, filters).",
1042
+ intentZh: "\u5206\u9875/\u6761\u4EF6\u67E5\u8BE2\u6D4F\u89C8\u5668 profile \u5217\u8868\u3002",
1043
+ triggersEn: "list profiles, search browsers, query accounts, show all profiles",
1044
+ triggersZh: "\u5217\u8868,\u67E5\u8BE2\u73AF\u5883,\u641C\u7D22profile,\u5217\u51FA\u6240\u6709\u6D4F\u89C8\u5668"
1045
+ },
1046
+ "get-opened-browser": {
1047
+ intentEn: "List browser profiles currently open on this device.",
1048
+ intentZh: "\u67E5\u770B\u672C\u673A\u5F53\u524D\u5DF2\u6253\u5F00\u7684\u6D4F\u89C8\u5668 profile\u3002",
1049
+ triggersEn: "opened browsers, running profiles, active local sessions",
1050
+ triggersZh: "\u5DF2\u6253\u5F00,\u6B63\u5728\u8FD0\u884C,\u5F53\u524D\u4F1A\u8BDD,\u672C\u5730\u6D3B\u8DC3"
1051
+ },
1052
+ "move-browser": {
1053
+ intentEn: "Move profiles to another group (regroup).",
1054
+ intentZh: "\u5C06 profile \u79FB\u52A8\u5230\u6307\u5B9A\u5206\u7EC4\u3002",
1055
+ triggersEn: "move to group, regroup profiles, change group",
1056
+ triggersZh: "\u79FB\u52A8\u5206\u7EC4,\u6362\u7EC4,\u5F52\u7C7B\u5230\u7EC4"
1057
+ },
1058
+ "get-profile-cookies": {
1059
+ intentEn: "Read cookies for one profile.",
1060
+ intentZh: "\u8BFB\u53D6\u5355\u4E2A profile \u7684 Cookie\u3002",
1061
+ triggersEn: "get cookies, export cookies, read cookie jar",
1062
+ triggersZh: "\u5BFC\u51FACookie,\u67E5\u770BCookie,\u8BFB\u53D6\u7AD9\u70B9Cookie"
1063
+ },
1064
+ "get-profile-ua": {
1065
+ intentEn: "Get User-Agent strings for up to 10 profiles.",
1066
+ intentZh: "\u6279\u91CF\u67E5\u8BE2\u6700\u591A 10 \u4E2A profile \u7684 UA\u3002",
1067
+ triggersEn: "user agent, UA string, browser UA",
1068
+ triggersZh: "UA,\u7528\u6237\u4EE3\u7406,\u6D4F\u89C8\u5668\u6807\u8BC6"
1069
+ },
1070
+ "close-all-profiles": {
1071
+ intentEn: "Close all opened profiles on this device.",
1072
+ intentZh: "\u5173\u95ED\u672C\u673A\u6240\u6709\u5DF2\u6253\u5F00\u7684\u73AF\u5883\u3002",
1073
+ triggersEn: "close everything, stop all browsers, shutdown all profiles",
1074
+ triggersZh: "\u5168\u90E8\u5173\u95ED,\u4E00\u952E\u5173\u73AF\u5883,\u5173\u6240\u6709\u6D4F\u89C8\u5668"
1075
+ },
1076
+ "new-fingerprint": {
1077
+ intentEn: "Generate a new fingerprint for up to 10 profiles.",
1078
+ intentZh: "\u4E3A\u6700\u591A 10 \u4E2A profile \u91CD\u65B0\u751F\u6210\u6307\u7EB9\u3002",
1079
+ triggersEn: "refresh fingerprint, regenerate fp, new device identity",
1080
+ triggersZh: "\u5237\u65B0\u6307\u7EB9,\u91CD\u65B0\u6307\u7EB9,\u6362\u8BBE\u5907\u6307\u7EB9"
1081
+ },
1082
+ "delete-cache-v2": {
1083
+ intentEn: "Clear selected local cache types for profiles.",
1084
+ intentZh: "\u6309\u7C7B\u578B\u6E05\u7406 profile \u672C\u5730\u7F13\u5B58\u3002",
1085
+ triggersEn: "clear cache, wipe storage, delete history cache",
1086
+ triggersZh: "\u6E05\u7F13\u5B58,\u5220\u5386\u53F2,\u6E05\u7406\u672C\u5730\u6570\u636E"
1087
+ },
1088
+ "share-profile": {
1089
+ intentEn: "Share profiles to another AdsPower account.",
1090
+ intentZh: "\u5C06 profile \u5206\u4EAB\u7ED9\u5176\u4ED6 AdsPower \u8D26\u53F7\u3002",
1091
+ triggersEn: "share account, transfer profile, send browser to user",
1092
+ triggersZh: "\u5206\u4EAB\u73AF\u5883,\u8F6C\u8BA9profile,\u53D1\u7ED9\u540C\u4E8B"
1093
+ },
1094
+ "get-browser-active": {
1095
+ intentEn: "Get active status/details for one profile.",
1096
+ intentZh: "\u67E5\u8BE2\u5355\u4E2A profile \u7684\u6D3B\u8DC3/\u8FD0\u884C\u4FE1\u606F\u3002",
1097
+ triggersEn: "is profile running, active status, browser state",
1098
+ triggersZh: "\u662F\u5426\u5728\u7EBF,\u6D3B\u8DC3\u72B6\u6001,\u8FD0\u884C\u4FE1\u606F"
1099
+ },
1100
+ "get-cloud-active": {
1101
+ intentEn: "Query cloud-side active status for many profile IDs.",
1102
+ intentZh: "\u6309 user_ids \u6279\u91CF\u67E5\u8BE2\u4E91\u7AEF\u6D3B\u8DC3\u72B6\u6001\u3002",
1103
+ triggersEn: "cloud status, remote active, team multi device caveat",
1104
+ triggersZh: "\u4E91\u7AEF\u72B6\u6001,\u8FDC\u7A0B\u662F\u5426\u6253\u5F00,\u591A\u8BBE\u5907\u6A21\u5F0F\u9650\u5236"
1105
+ },
1106
+ "create-group": {
1107
+ intentEn: "Create a browser profile group.",
1108
+ intentZh: "\u65B0\u5EFA\u6D4F\u89C8\u5668\u5206\u7EC4\u3002",
1109
+ triggersEn: "new group, add folder for profiles",
1110
+ triggersZh: "\u65B0\u5EFA\u5206\u7EC4,\u521B\u5EFA\u7EC4,\u73AF\u5883\u5206\u7EC4"
1111
+ },
1112
+ "update-group": {
1113
+ intentEn: "Rename or update a group.",
1114
+ intentZh: "\u91CD\u547D\u540D\u6216\u66F4\u65B0\u5206\u7EC4\u4FE1\u606F\u3002",
1115
+ triggersEn: "rename group, edit group",
1116
+ triggersZh: "\u6539\u7EC4\u540D,\u66F4\u65B0\u5206\u7EC4"
1117
+ },
1118
+ "get-group-list": {
1119
+ intentEn: "List groups with optional name search.",
1120
+ intentZh: "\u5206\u9875\u67E5\u8BE2\u5206\u7EC4\u5217\u8868\uFF0C\u53EF\u6309\u540D\u79F0\u641C\u7D22\u3002",
1121
+ triggersEn: "list groups, search group name",
1122
+ triggersZh: "\u5206\u7EC4\u5217\u8868,\u67E5\u7EC4\u540D"
1123
+ },
1124
+ "check-status": {
1125
+ intentEn: "Check Local API availability on this machine.",
1126
+ intentZh: "\u68C0\u6D4B\u672C\u673A Local API \u662F\u5426\u53EF\u7528\u3002",
1127
+ triggersEn: "API health, connection status, ping AdsPower API",
1128
+ triggersZh: "\u63A5\u53E3\u901A\u4E0D\u901A,\u68C0\u6D4BAPI,\u8FDE\u63A5\u72B6\u6001"
1129
+ },
1130
+ "get-application-list": {
1131
+ intentEn: "List application/extension categories with pagination.",
1132
+ intentZh: "\u5206\u9875\u83B7\u53D6\u5E94\u7528/\u6269\u5C55\u5206\u7C7B\u5217\u8868\u3002",
1133
+ triggersEn: "categories, extension list, application catalog",
1134
+ triggersZh: "\u5E94\u7528\u5206\u7C7B,\u6269\u5C55\u76EE\u5F55,\u7C7B\u522B\u5217\u8868"
1135
+ },
1136
+ "create-proxy": {
1137
+ intentEn: "Create one or more proxy entries.",
1138
+ intentZh: "\u65B0\u5EFA\u4E00\u6761\u6216\u591A\u6761\u4EE3\u7406\u914D\u7F6E\u3002",
1139
+ triggersEn: "add proxy, new proxy row",
1140
+ triggersZh: "\u6DFB\u52A0\u4EE3\u7406,\u65B0\u5EFA\u4EE3\u7406"
1141
+ },
1142
+ "update-proxy": {
1143
+ intentEn: "Update an existing proxy entry.",
1144
+ intentZh: "\u66F4\u65B0\u5DF2\u6709\u4EE3\u7406\u9879\u3002",
1145
+ triggersEn: "edit proxy, change proxy host",
1146
+ triggersZh: "\u4FEE\u6539\u4EE3\u7406,\u66F4\u65B0\u4EE3\u7406"
1147
+ },
1148
+ "get-proxy-list": {
1149
+ intentEn: "List proxies with filters/pagination.",
1150
+ intentZh: "\u5206\u9875/\u6761\u4EF6\u67E5\u8BE2\u4EE3\u7406\u5217\u8868\u3002",
1151
+ triggersEn: "list proxies, search proxy",
1152
+ triggersZh: "\u4EE3\u7406\u5217\u8868,\u67E5\u4EE3\u7406"
1153
+ },
1154
+ "delete-proxy": {
1155
+ intentEn: "Delete proxies by id list.",
1156
+ intentZh: "\u6309 ID \u5217\u8868\u5220\u9664\u4EE3\u7406\u3002",
1157
+ triggersEn: "remove proxy, delete proxy entries",
1158
+ triggersZh: "\u5220\u9664\u4EE3\u7406,\u79FB\u9664\u4EE3\u7406"
1159
+ },
1160
+ "get-tag-list": {
1161
+ intentEn: "List browser tags.",
1162
+ intentZh: "\u67E5\u8BE2\u6D4F\u89C8\u5668\u6807\u7B7E\u5217\u8868\u3002",
1163
+ triggersEn: "list tags, label list",
1164
+ triggersZh: "\u6807\u7B7E\u5217\u8868,\u67E5\u770B\u6807\u7B7E"
1165
+ },
1166
+ "create-tag": {
1167
+ intentEn: "Create tags (batch).",
1168
+ intentZh: "\u6279\u91CF\u521B\u5EFA\u6807\u7B7E\u3002",
1169
+ triggersEn: "new tag, add label",
1170
+ triggersZh: "\u65B0\u5EFA\u6807\u7B7E,\u6DFB\u52A0\u6807\u7B7E"
1171
+ },
1172
+ "update-tag": {
1173
+ intentEn: "Update existing tags (batch).",
1174
+ intentZh: "\u6279\u91CF\u66F4\u65B0\u6807\u7B7E\u3002",
1175
+ triggersEn: "rename tag, change tag color",
1176
+ triggersZh: "\u6539\u6807\u7B7E\u540D,\u6539\u989C\u8272"
1177
+ },
1178
+ "delete-tag": {
1179
+ intentEn: "Delete tags by id list.",
1180
+ intentZh: "\u6309 ID \u5220\u9664\u6807\u7B7E\u3002",
1181
+ triggersEn: "remove tags",
1182
+ triggersZh: "\u5220\u9664\u6807\u7B7E"
1183
+ },
1184
+ "download-kernel": {
1185
+ intentEn: "Download or update a browser kernel version.",
1186
+ intentZh: "\u4E0B\u8F7D\u6216\u66F4\u65B0\u6307\u5B9A\u5185\u6838\u7248\u672C\u3002",
1187
+ triggersEn: "download chrome kernel, fetch firefox kernel",
1188
+ triggersZh: "\u4E0B\u8F7D\u5185\u6838,\u66F4\u65B0Chrome\u5185\u6838"
1189
+ },
1190
+ "get-kernel-list": {
1191
+ intentEn: "List supported kernel versions (optional type filter).",
1192
+ intentZh: "\u67E5\u8BE2\u652F\u6301\u7684\u5185\u6838\u7248\u672C\u5217\u8868\u3002",
1193
+ triggersEn: "kernel versions, supported browsers list",
1194
+ triggersZh: "\u5185\u6838\u5217\u8868,\u53EF\u7528\u7248\u672C"
1195
+ },
1196
+ "update-patch": {
1197
+ intentEn: "Update AdsPower client patch channel.",
1198
+ intentZh: "\u5C06 AdsPower \u5BA2\u6237\u7AEF\u66F4\u65B0\u5230\u8865\u4E01\u901A\u9053\u7248\u672C\u3002",
1199
+ triggersEn: "upgrade client, patch update, stable beta channel",
1200
+ triggersZh: "\u5347\u7EA7\u5BA2\u6237\u7AEF,\u8865\u4E01\u66F4\u65B0,\u7A33\u5B9A\u7248\u6D4B\u8BD5\u7248"
1201
+ },
1202
+ "connect-browser-with-ws": {
1203
+ intentEn: "Attach Playwright automation using ws from open-browser.",
1204
+ intentZh: "\u7528 open-browser \u8FD4\u56DE\u7684 ws \u8FDE\u63A5\u81EA\u52A8\u5316\uFF08Playwright\uFF09\u3002",
1205
+ triggersEn: "connect puppeteer, attach playwright, ws automation",
1206
+ triggersZh: "\u8FDE\u63A5\u81EA\u52A8\u5316,\u6302\u4E0APlaywright,\u7528ws\u63A7\u5236"
1207
+ },
1208
+ "open-new-page": {
1209
+ intentEn: "Open a new page in the connected automation session.",
1210
+ intentZh: "\u5728\u5DF2\u8FDE\u63A5\u4F1A\u8BDD\u4E2D\u6253\u5F00\u65B0\u6807\u7B7E\u9875/\u9875\u9762\u3002",
1211
+ triggersEn: "new tab, new page",
1212
+ triggersZh: "\u65B0\u6807\u7B7E\u9875,\u65B0\u9875\u9762"
1213
+ },
1214
+ "navigate": {
1215
+ intentEn: "Navigate current automation page to a URL.",
1216
+ intentZh: "\u81EA\u52A8\u5316\u5F53\u524D\u9875\u8DF3\u8F6C\u5230 URL\u3002",
1217
+ triggersEn: "goto url, open url in automation",
1218
+ triggersZh: "\u8DF3\u8F6C\u7F51\u5740,\u6253\u5F00\u94FE\u63A5"
1219
+ },
1220
+ "screenshot": {
1221
+ intentEn: "Capture screenshot of the automation page.",
1222
+ intentZh: "\u622A\u53D6\u81EA\u52A8\u5316\u5F53\u524D\u9875\u9762\u622A\u56FE\u3002",
1223
+ triggersEn: "screenshot, capture page image",
1224
+ triggersZh: "\u622A\u56FE,\u622A\u5C4F"
1225
+ },
1226
+ "get-page-visible-text": {
1227
+ intentEn: "Read visible text of the current page.",
1228
+ intentZh: "\u8BFB\u53D6\u5F53\u524D\u9875\u53EF\u89C1\u6587\u672C\u3002",
1229
+ triggersEn: "visible text, page text content",
1230
+ triggersZh: "\u53EF\u89C1\u6587\u5B57,\u9875\u9762\u6587\u672C"
1231
+ },
1232
+ "get-page-html": {
1233
+ intentEn: "Read HTML of the current page.",
1234
+ intentZh: "\u8BFB\u53D6\u5F53\u524D\u9875 HTML\u3002",
1235
+ triggersEn: "page source, dom html",
1236
+ triggersZh: "\u7F51\u9875\u6E90\u7801,HTML"
1237
+ },
1238
+ "click-element": {
1239
+ intentEn: "Click an element by selector in automation session.",
1240
+ intentZh: "\u5728\u81EA\u52A8\u5316\u4F1A\u8BDD\u4E2D\u6309\u9009\u62E9\u5668\u70B9\u51FB\u5143\u7D20\u3002",
1241
+ triggersEn: "click button, tap element",
1242
+ triggersZh: "\u70B9\u51FB\u6309\u94AE,\u70B9\u5143\u7D20"
1243
+ },
1244
+ "fill-input": {
1245
+ intentEn: "Fill an input field by selector.",
1246
+ intentZh: "\u6309\u9009\u62E9\u5668\u586B\u5199\u8F93\u5165\u6846\u3002",
1247
+ triggersEn: "type text, enter value, input field",
1248
+ triggersZh: "\u8F93\u5165\u6587\u5B57,\u586B\u8868\u5355"
1249
+ },
1250
+ "select-option": {
1251
+ intentEn: "Select a dropdown option by selector and value.",
1252
+ intentZh: "\u4E0B\u62C9\u6846\u6309 selector \u4E0E value \u9009\u62E9\u3002",
1253
+ triggersEn: "dropdown select, pick option",
1254
+ triggersZh: "\u4E0B\u62C9\u9009\u62E9,\u9009\u9009\u9879"
1255
+ },
1256
+ "hover-element": {
1257
+ intentEn: "Hover an element by selector.",
1258
+ intentZh: "\u60AC\u505C\u5230\u6307\u5B9A\u5143\u7D20\u3002",
1259
+ triggersEn: "mouse over, hover menu",
1260
+ triggersZh: "\u9F20\u6807\u60AC\u505C,\u5212\u8FC7\u83DC\u5355"
1261
+ },
1262
+ "scroll-element": {
1263
+ intentEn: "Scroll an element into view or by selector.",
1264
+ intentZh: "\u6EDA\u52A8\u6307\u5B9A\u5143\u7D20\u6216\u533A\u57DF\u3002",
1265
+ triggersEn: "scroll into view, page scroll",
1266
+ triggersZh: "\u6EDA\u52A8\u5230\u53EF\u89C1,\u9875\u9762\u6EDA\u52A8"
1267
+ },
1268
+ "press-key": {
1269
+ intentEn: "Press a keyboard key (optional focused selector).",
1270
+ intentZh: "\u6A21\u62DF\u6309\u952E\uFF08\u53EF\u9009\u9650\u5B9A\u5728\u5143\u7D20\u4E0A\uFF09\u3002",
1271
+ triggersEn: "hit Enter, keyboard shortcut",
1272
+ triggersZh: "\u6309\u56DE\u8F66,\u5FEB\u6377\u952E"
1273
+ },
1274
+ "evaluate-script": {
1275
+ intentEn: "Run JavaScript in the page context.",
1276
+ intentZh: "\u5728\u9875\u9762\u4E0A\u4E0B\u6587\u6267\u884C JS\u3002",
1277
+ triggersEn: "execute js, run script in page",
1278
+ triggersZh: "\u6267\u884C\u811A\u672C,\u9875\u9762JS"
1279
+ },
1280
+ "drag-element": {
1281
+ intentEn: "Drag an element to a target element.",
1282
+ intentZh: "\u62D6\u62FD\u5143\u7D20\u5230\u53E6\u4E00\u5143\u7D20\u3002",
1283
+ triggersEn: "drag and drop, dnd",
1284
+ triggersZh: "\u62D6\u62FD,\u62D6\u653E"
1285
+ },
1286
+ "iframe-click-element": {
1287
+ intentEn: "Click inside an iframe by iframe and inner selectors.",
1288
+ intentZh: "\u5728 iframe \u5185\u70B9\u51FB\u5B50\u5143\u7D20\u3002",
1289
+ triggersEn: "iframe click, nested frame",
1290
+ triggersZh: "\u6846\u67B6\u5185\u70B9\u51FB,iframe\u91CC\u70B9"
1291
+ }
1292
+ };
1293
+ function formatDescription(rec) {
1294
+ return `${rec.intentEn} / ${rec.intentZh} | Triggers: ${rec.triggersEn}; ${rec.triggersZh}`;
1295
+ }
1296
+ function buildMcpToolDescription(toolName, legacyFallback) {
1297
+ const rec = TOOL_INTENT_BY_NAME[toolName];
1298
+ return rec ? formatDescription(rec) : legacyFallback;
1299
+ }
1300
+ function buildCliCommandDescription(commandName, legacyFallback) {
1301
+ return buildMcpToolDescription(commandName, legacyFallback);
1302
+ }
1303
+
1304
+ // ../core/src/handlers/browser.ts
1305
+ var import_node_os = __toESM(require("os"));
1306
+
623
1307
  // ../core/src/utils/requestBuilder.ts
624
- function buildRequestBody(params) {
1308
+ function toContractValue(value) {
1309
+ if (Array.isArray(value)) {
1310
+ return value;
1311
+ }
1312
+ if (value && typeof value === "object") {
1313
+ return buildNestedConfig(value);
1314
+ }
1315
+ return value;
1316
+ }
1317
+ function buildRequestBodyFor(command, params) {
625
1318
  const requestBody = {};
626
- const basicFields = {
627
- groupId: "group_id",
628
- username: "username",
629
- password: "password",
630
- cookie: "cookie",
631
- fakey: "fakey",
632
- name: "name",
633
- platform: "platform",
634
- remark: "remark",
635
- proxyid: "proxyid",
636
- repeatConfig: "repeat_config",
637
- ignoreCookieError: "ignore_cookie_error",
638
- tabs: "tabs",
639
- ip: "ip",
640
- country: "country",
641
- region: "region",
642
- city: "city",
643
- ipchecker: "ipchecker",
644
- categoryId: "category_id",
645
- launchArgs: "launch_args",
646
- profileId: "profile_id",
647
- profileTagIds: "profile_tag_ids",
648
- tagsUpdateType: "tags_update_type"
649
- };
650
- Object.entries(basicFields).forEach(([paramKey, key]) => {
651
- const value = params[paramKey];
1319
+ const contract = LOCAL_API_CONTRACTS[command];
1320
+ Object.entries(contract.params).forEach(([inputName, config2]) => {
1321
+ if (config2.location !== "body") {
1322
+ return;
1323
+ }
1324
+ const value = params[inputName];
652
1325
  if (value !== void 0) {
653
- requestBody[key] = value;
1326
+ requestBody[config2.apiName] = toContractValue(value);
654
1327
  }
655
1328
  });
656
- if (params.userProxyConfig) {
657
- const proxyConfig = buildNestedConfig(params.userProxyConfig);
658
- if (Object.keys(proxyConfig).length > 0) {
659
- requestBody.user_proxy_config = proxyConfig;
1329
+ return requestBody;
1330
+ }
1331
+ function buildQueryParamsFor(command, params) {
1332
+ const query = new URLSearchParams();
1333
+ const contract = LOCAL_API_CONTRACTS[command];
1334
+ Object.entries(contract.params).forEach(([inputName, config2]) => {
1335
+ if (config2.location !== "query") {
1336
+ return;
660
1337
  }
661
- }
662
- if (params.fingerprintConfig) {
663
- const fpConfig = buildNestedConfig(params.fingerprintConfig);
664
- if (Object.keys(fpConfig).length > 0) {
665
- requestBody.fingerprint_config = fpConfig;
1338
+ const value = params[inputName];
1339
+ if (value === void 0) {
1340
+ return;
666
1341
  }
667
- }
668
- return requestBody;
1342
+ query.set(config2.apiName, Array.isArray(value) ? value.join(",") : String(value));
1343
+ });
1344
+ return query;
669
1345
  }
670
1346
  function buildNestedConfig(config2) {
671
1347
  const result = {};
672
1348
  Object.entries(config2).forEach(([key, value]) => {
673
1349
  if (value !== void 0) {
674
- if (typeof value === "object" && value !== null) {
1350
+ if (Array.isArray(value)) {
1351
+ result[key] = value;
1352
+ } else if (typeof value === "object" && value !== null) {
675
1353
  const nestedConfig = buildNestedConfig(value);
676
1354
  if (Object.keys(nestedConfig).length > 0) {
677
1355
  result[key] = nestedConfig;
@@ -684,47 +1362,58 @@ function buildNestedConfig(config2) {
684
1362
  return result;
685
1363
  }
686
1364
 
1365
+ // ../core/src/utils/openBrowserHeadless.ts
1366
+ function isTruthyCi(env) {
1367
+ const v = env.CI;
1368
+ return v === "true" || v === "1" || v === "True";
1369
+ }
1370
+ function linuxLooksHeadless(env) {
1371
+ const d = (env.DISPLAY ?? "").trim();
1372
+ const w = (env.WAYLAND_DISPLAY ?? "").trim();
1373
+ return d === "" && w === "";
1374
+ }
1375
+ function resolveOpenBrowserHeadless(params, env, platform) {
1376
+ if (params.headless !== void 0) {
1377
+ return { params: { ...params }, didAutoSetHeadless: false };
1378
+ }
1379
+ let needHeadless = false;
1380
+ if (isTruthyCi(env)) {
1381
+ needHeadless = true;
1382
+ } else if (platform === "linux" && linuxLooksHeadless(env)) {
1383
+ needHeadless = true;
1384
+ }
1385
+ if (!needHeadless) {
1386
+ return { params: { ...params }, didAutoSetHeadless: false };
1387
+ }
1388
+ return {
1389
+ params: { ...params, headless: "1" },
1390
+ didAutoSetHeadless: true
1391
+ };
1392
+ }
1393
+
687
1394
  // ../core/src/handlers/browser.ts
688
1395
  var browserHandlers = {
689
- async openBrowser({ profileNo, profileId, ipTab, launchArgs, clearCacheAfterClosing, cdpMask }) {
690
- const requestBody = {};
691
- if (profileId) {
692
- requestBody.profile_id = profileId;
693
- }
694
- if (profileNo) {
695
- requestBody.profile_no = profileNo;
696
- }
697
- if (ipTab) {
698
- requestBody.ip_tab = ipTab;
699
- }
700
- if (launchArgs) {
701
- requestBody.launch_args = launchArgs;
702
- }
703
- if (clearCacheAfterClosing) {
704
- requestBody.delete_cache = clearCacheAfterClosing;
705
- }
706
- if (cdpMask) {
707
- requestBody.cdp_mask = cdpMask;
708
- }
1396
+ async openBrowser(params) {
1397
+ const { params: resolvedParams, didAutoSetHeadless } = resolveOpenBrowserHeadless(
1398
+ params,
1399
+ process.env,
1400
+ import_node_os.default.platform()
1401
+ );
1402
+ const requestBody = buildRequestBodyFor("open-browser", resolvedParams);
709
1403
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.START_BROWSER}`, requestBody);
710
1404
  if (response.data.code === 0) {
1405
+ 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)." : "";
711
1406
  return `Browser opened successfully with: ${Object.entries(response.data.data).map(([key, value]) => {
712
1407
  if (value && typeof value === "object") {
713
1408
  return Object.entries(value).map(([key2, value2]) => `ws.${key2}: ${value2}`).join("\n");
714
1409
  }
715
1410
  return `${key}: ${value}`;
716
- }).join("\n")}`;
1411
+ }).join("\n")}${autoNote}`;
717
1412
  }
718
1413
  throw new Error(`Failed to open browser: ${response.data.msg}`);
719
1414
  },
720
- async closeBrowser({ profileId, profileNo }) {
721
- const requestBody = {};
722
- if (profileId) {
723
- requestBody.profile_id = profileId;
724
- }
725
- if (profileNo) {
726
- requestBody.profile_no = profileNo;
727
- }
1415
+ async closeBrowser(params) {
1416
+ const requestBody = buildRequestBodyFor("close-browser", params);
728
1417
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CLOSE_BROWSER}`, requestBody);
729
1418
  if (response.data.code === 0) {
730
1419
  return "Browser closed successfully";
@@ -732,7 +1421,7 @@ var browserHandlers = {
732
1421
  throw new Error(`Failed to close browser: ${response.data.msg}`);
733
1422
  },
734
1423
  async createBrowser(params) {
735
- const requestBody = buildRequestBody(params);
1424
+ const requestBody = buildRequestBodyFor("create-browser", params);
736
1425
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CREATE_BROWSER}`, requestBody);
737
1426
  if (response.data.code === 0) {
738
1427
  return `Browser created successfully with: ${Object.entries(response.data.data).map(([key, value]) => `${key}: ${value}`).join("\n")}`;
@@ -740,58 +1429,25 @@ var browserHandlers = {
740
1429
  throw new Error(`Failed to create browser: ${response.data.msg}`);
741
1430
  },
742
1431
  async updateBrowser(params) {
743
- const requestBody = buildRequestBody(params);
1432
+ const requestBody = buildRequestBodyFor("update-browser", params);
744
1433
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_BROWSER}`, requestBody);
745
1434
  if (response.data.code === 0) {
746
1435
  return `Browser updated successfully with: ${Object.entries(response.data.data || {}).map(([key, value]) => `${key}: ${value}`).join("\n")}`;
747
1436
  }
748
1437
  throw new Error(`Failed to update browser: ${response.data.msg}`);
749
1438
  },
750
- async deleteBrowser({ profileIds }) {
751
- const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.DELETE_BROWSER}`, {
752
- profile_id: profileIds
753
- });
1439
+ async deleteBrowser(params) {
1440
+ const response = await getApiClient().post(
1441
+ `${getLocalApiBase()}${API_ENDPOINTS.DELETE_BROWSER}`,
1442
+ buildRequestBodyFor("delete-browser", params)
1443
+ );
754
1444
  if (response.data.code === 0) {
755
- return `Browsers deleted successfully: ${profileIds.join(", ")}`;
1445
+ return `Browsers deleted successfully: ${params.profile_id.join(", ")}`;
756
1446
  }
757
1447
  throw new Error(`Failed to delete browsers: ${response.data.msg}`);
758
1448
  },
759
1449
  async getBrowserList(params) {
760
- const { groupId, limit, page, profileId, profileNo, sortType, sortOrder, tag_ids, tags_filter, name, name_filter } = params;
761
- const requestBody = {};
762
- if (limit !== void 0) {
763
- requestBody.limit = limit;
764
- }
765
- if (page !== void 0) {
766
- requestBody.page = page;
767
- }
768
- if (profileId && profileId.length > 0) {
769
- requestBody.profile_id = profileId;
770
- }
771
- if (profileNo && profileNo.length > 0) {
772
- requestBody.profile_no = profileNo;
773
- }
774
- if (groupId !== void 0) {
775
- requestBody.group_id = groupId;
776
- }
777
- if (sortType) {
778
- requestBody.sort_type = sortType;
779
- }
780
- if (sortOrder) {
781
- requestBody.sort_order = sortOrder;
782
- }
783
- if (tag_ids && tag_ids.length > 0) {
784
- requestBody.tag_ids = tag_ids;
785
- }
786
- if (tags_filter) {
787
- requestBody.tags_filter = tags_filter;
788
- }
789
- if (name) {
790
- requestBody.name = name;
791
- }
792
- if (name_filter) {
793
- requestBody.name_filter = name_filter;
794
- }
1450
+ const requestBody = buildRequestBodyFor("get-browser-list", params);
795
1451
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_BROWSER_LIST}`, requestBody);
796
1452
  if (response.data.code === 0) {
797
1453
  return `Browser list: ${JSON.stringify(response.data.data.list, null, 2)}`;
@@ -805,38 +1461,25 @@ var browserHandlers = {
805
1461
  }
806
1462
  throw new Error(`Failed to get opened browsers: ${response.data.msg}`);
807
1463
  },
808
- async moveBrowser({ groupId, userIds }) {
809
- const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.MOVE_BROWSER}`, {
810
- group_id: groupId,
811
- user_ids: userIds
812
- });
1464
+ async moveBrowser(params) {
1465
+ const requestBody = buildRequestBodyFor("move-browser", params);
1466
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.MOVE_BROWSER}`, requestBody);
1467
+ const { group_id, user_ids } = params;
813
1468
  if (response.data.code === 0) {
814
- return `Browsers moved successfully to group ${groupId}: ${userIds.join(", ")}`;
1469
+ return `Browsers moved successfully to group ${group_id}: ${user_ids.join(", ")}`;
815
1470
  }
816
1471
  throw new Error(`Failed to move browsers: ${response.data.msg}`);
817
1472
  },
818
- async getProfileCookies({ profileId, profileNo }) {
819
- const params = new URLSearchParams();
820
- if (profileId) {
821
- params.set("profile_id", profileId);
822
- }
823
- if (profileNo) {
824
- params.set("profile_no", profileNo);
825
- }
826
- const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_PROFILE_COOKIES}`, { params });
1473
+ async getProfileCookies(params) {
1474
+ const query = buildQueryParamsFor("get-profile-cookies", params);
1475
+ const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_PROFILE_COOKIES}`, { params: query });
827
1476
  if (response.data.code === 0) {
828
1477
  return `Profile cookies: ${JSON.stringify(response.data.data, null, 2)}`;
829
1478
  }
830
1479
  throw new Error(`Failed to get profile cookies: ${response.data.msg}`);
831
1480
  },
832
- async getProfileUa({ profileId, profileNo }) {
833
- const requestBody = {};
834
- if (profileId && profileId.length > 0) {
835
- requestBody.profile_id = profileId;
836
- }
837
- if (profileNo && profileNo.length > 0) {
838
- requestBody.profile_no = profileNo;
839
- }
1481
+ async getProfileUa(params) {
1482
+ const requestBody = buildRequestBodyFor("get-profile-ua", params);
840
1483
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_PROFILE_UA}`, requestBody);
841
1484
  if (response.data.code === 0) {
842
1485
  return `Profile User-Agent: ${JSON.stringify(response.data.data, null, 2)}`;
@@ -850,65 +1493,43 @@ var browserHandlers = {
850
1493
  }
851
1494
  throw new Error(`Failed to close all profiles: ${response.data.msg}`);
852
1495
  },
853
- async newFingerprint({ profileId, profileNo }) {
854
- const requestBody = {};
855
- if (profileId && profileId.length > 0) {
856
- requestBody.profile_id = profileId;
857
- }
858
- if (profileNo && profileNo.length > 0) {
859
- requestBody.profile_no = profileNo;
860
- }
1496
+ async newFingerprint(params) {
1497
+ const requestBody = buildRequestBodyFor("new-fingerprint", params);
861
1498
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.NEW_FINGERPRINT}`, requestBody);
862
1499
  if (response.data.code === 0) {
863
1500
  return `New fingerprint created: ${JSON.stringify(response.data.data, null, 2)}`;
864
1501
  }
865
1502
  throw new Error(`Failed to create new fingerprint: ${response.data.msg}`);
866
1503
  },
867
- async deleteCacheV2({ profileIds, type }) {
868
- const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.DELETE_CACHE_V2}`, {
869
- profile_id: profileIds,
870
- type
871
- });
1504
+ async deleteCacheV2(params) {
1505
+ const response = await getApiClient().post(
1506
+ `${getLocalApiBase()}${API_ENDPOINTS.DELETE_CACHE_V2}`,
1507
+ buildRequestBodyFor("delete-cache-v2", params)
1508
+ );
872
1509
  if (response.data.code === 0) {
873
- return `Cache deleted successfully for profiles: ${profileIds.join(", ")}`;
1510
+ return `Cache deleted successfully for profiles: ${params.profile_id.join(", ")}`;
874
1511
  }
875
1512
  throw new Error(`Failed to delete cache: ${response.data.msg}`);
876
1513
  },
877
- async shareProfile({ profileIds, receiver, shareType, content }) {
878
- const requestBody = {
879
- profile_id: profileIds,
880
- receiver
881
- };
882
- if (shareType !== void 0) {
883
- requestBody.share_type = shareType;
884
- }
885
- if (content !== void 0) {
886
- requestBody.content = content;
887
- }
1514
+ async shareProfile(params) {
1515
+ const requestBody = buildRequestBodyFor("share-profile", params);
888
1516
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.SHARE_PROFILE}`, requestBody);
889
1517
  if (response.data.code === 0) {
890
- return `Profiles shared successfully: ${profileIds.join(", ")}`;
1518
+ return `Profiles shared successfully: ${params.profile_id.join(", ")}`;
891
1519
  }
892
1520
  throw new Error(`Failed to share profiles: ${response.data.msg}`);
893
1521
  },
894
- async getBrowserActive({ profileId, profileNo }) {
895
- const params = new URLSearchParams();
896
- if (profileId) {
897
- params.set("profile_id", profileId);
898
- }
899
- if (profileNo) {
900
- params.set("profile_no", profileNo);
901
- }
902
- const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_BROWSER_ACTIVE}`, { params });
1522
+ async getBrowserActive(params) {
1523
+ const query = buildQueryParamsFor("get-browser-active", params);
1524
+ const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_BROWSER_ACTIVE}`, { params: query });
903
1525
  if (response.data.code === 0) {
904
1526
  return `Browser active info: ${JSON.stringify(response.data.data, null, 2)}`;
905
1527
  }
906
1528
  throw new Error(`Failed to get browser active: ${response.data.msg}`);
907
1529
  },
908
- async getCloudActive({ userIds }) {
909
- const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_CLOUD_ACTIVE}`, {
910
- user_ids: userIds
911
- });
1530
+ async getCloudActive(params) {
1531
+ const requestBody = buildRequestBodyFor("get-cloud-active", params);
1532
+ const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_CLOUD_ACTIVE}`, requestBody);
912
1533
  if (response.data.code === 0) {
913
1534
  return `Cloud active browsers: ${JSON.stringify(response.data.data, null, 2)}`;
914
1535
  }
@@ -918,46 +1539,31 @@ var browserHandlers = {
918
1539
 
919
1540
  // ../core/src/handlers/group.ts
920
1541
  var groupHandlers = {
921
- async createGroup({ groupName, remark }) {
922
- const requestBody = {
923
- group_name: groupName
924
- };
925
- if (remark !== void 0) {
926
- requestBody.remark = remark;
927
- }
1542
+ async createGroup(params) {
1543
+ const requestBody = buildRequestBodyFor("create-group", params);
928
1544
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CREATE_GROUP}`, requestBody);
1545
+ const { group_name, remark } = params;
929
1546
  if (response.data.code === 0) {
930
- return `Group created successfully with name: ${groupName}${remark ? `, remark: ${remark}` : ""}`;
1547
+ return `Group created successfully with name: ${group_name}${remark ? `, remark: ${remark}` : ""}`;
931
1548
  }
932
1549
  throw new Error(`Failed to create group: ${response.data.msg}`);
933
1550
  },
934
- async updateGroup({ groupId, groupName, remark }) {
935
- const requestBody = {
936
- group_id: groupId,
937
- group_name: groupName
938
- };
939
- if (remark !== void 0) {
940
- requestBody.remark = remark;
941
- }
1551
+ async updateGroup(params) {
1552
+ const requestBody = buildRequestBodyFor("update-group", params);
942
1553
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_GROUP}`, requestBody);
1554
+ const { group_id, group_name, remark } = params;
943
1555
  if (response.data.code === 0) {
944
- return `Group updated successfully with id: ${groupId}, name: ${groupName}${remark !== void 0 ? `, remark: ${remark === null ? "(cleared)" : remark}` : ""}`;
1556
+ return `Group updated successfully with id: ${group_id}, name: ${group_name}${remark !== void 0 ? `, remark: ${remark === null ? "(cleared)" : remark}` : ""}`;
945
1557
  }
946
1558
  throw new Error(`Failed to update group: ${response.data.msg}`);
947
1559
  },
948
- async getGroupList({ groupName, size, page }) {
949
- const params = new URLSearchParams();
950
- if (groupName) {
951
- params.set("group_name", groupName);
952
- }
953
- if (size) {
954
- params.set("page_size", size.toString());
955
- }
956
- if (page) {
957
- params.set("page", page.toString());
1560
+ async getGroupList(params) {
1561
+ const query = buildQueryParamsFor("get-group-list", params);
1562
+ const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_GROUP_LIST}`, { params: query });
1563
+ if (response.data.code === 0) {
1564
+ return `Group list: ${JSON.stringify(response.data.data.list, null, 2)}`;
958
1565
  }
959
- const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_GROUP_LIST}`, { params });
960
- return `Group list: ${JSON.stringify(response.data.data.list, null, 2)}`;
1566
+ throw new Error(`Failed to get group list: ${response.data.msg}`);
961
1567
  }
962
1568
  };
963
1569
 
@@ -967,54 +1573,14 @@ var applicationHandlers = {
967
1573
  const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.STATUS}`);
968
1574
  return `Connection status: ${JSON.stringify(response.data, null, 2)}`;
969
1575
  },
970
- async getApplicationList({ category_id, page, limit }) {
971
- const params = new URLSearchParams();
972
- if (category_id) {
973
- params.set("category_id", category_id);
974
- }
975
- if (page !== void 0) {
976
- params.set("page", page.toString());
977
- }
978
- if (limit !== void 0) {
979
- params.set("limit", limit.toString());
980
- }
981
- const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_APPLICATION_LIST}`, { params });
1576
+ async getApplicationList(params) {
1577
+ const query = buildQueryParamsFor("get-application-list", params);
1578
+ const response = await getApiClient().get(`${getLocalApiBase()}${API_ENDPOINTS.GET_APPLICATION_LIST}`, { params: query });
982
1579
  return `Application list: ${JSON.stringify(response.data.data.list, null, 2)}`;
983
1580
  }
984
1581
  };
985
1582
 
986
1583
  // ../core/src/handlers/proxy.ts
987
- function buildProxyRequestBody(params) {
988
- const requestBody = {};
989
- if (params.proxyId) {
990
- requestBody.proxy_id = params.proxyId;
991
- }
992
- if (params.type !== void 0) {
993
- requestBody.type = params.type;
994
- }
995
- if (params.host !== void 0) {
996
- requestBody.host = params.host;
997
- }
998
- if (params.port !== void 0) {
999
- requestBody.port = params.port;
1000
- }
1001
- if (params.user !== void 0) {
1002
- requestBody.user = params.user;
1003
- }
1004
- if (params.password !== void 0) {
1005
- requestBody.password = params.password;
1006
- }
1007
- if (params.proxyUrl !== void 0) {
1008
- requestBody.proxy_url = params.proxyUrl;
1009
- }
1010
- if (params.remark !== void 0) {
1011
- requestBody.remark = params.remark;
1012
- }
1013
- if (params.ipchecker !== void 0) {
1014
- requestBody.ipchecker = params.ipchecker;
1015
- }
1016
- return requestBody;
1017
- }
1018
1584
  function buildCreateProxyRequestBody(proxy) {
1019
1585
  const requestBody = {};
1020
1586
  requestBody.type = proxy.type;
@@ -1039,7 +1605,7 @@ function buildCreateProxyRequestBody(proxy) {
1039
1605
  }
1040
1606
  var proxyHandlers = {
1041
1607
  async createProxy(params) {
1042
- const requestBody = params.proxies.map((proxy) => buildCreateProxyRequestBody(proxy));
1608
+ const requestBody = params.map((proxy) => buildCreateProxyRequestBody(proxy));
1043
1609
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.CREATE_PROXY}`, requestBody);
1044
1610
  if (response.data.code === 0) {
1045
1611
  return `Proxy created successfully with: ${Object.entries(response.data.data || {}).map(([key, value]) => `${key}: ${value}`).join("\n")}`;
@@ -1047,7 +1613,7 @@ var proxyHandlers = {
1047
1613
  throw new Error(`Failed to create proxy: ${response.data.msg}`);
1048
1614
  },
1049
1615
  async updateProxy(params) {
1050
- const requestBody = buildProxyRequestBody(params);
1616
+ const requestBody = buildRequestBodyFor("update-proxy", params);
1051
1617
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.UPDATE_PROXY}`, requestBody);
1052
1618
  if (response.data.code === 0) {
1053
1619
  return `Proxy updated successfully with: ${Object.entries(response.data.data || {}).map(([key, value]) => `${key}: ${value}`).join("\n")}`;
@@ -1055,29 +1621,21 @@ var proxyHandlers = {
1055
1621
  throw new Error(`Failed to update proxy: ${response.data.msg}`);
1056
1622
  },
1057
1623
  async getProxyList(params) {
1058
- const { limit, page, proxyId } = params;
1059
- const requestBody = {};
1060
- if (limit !== void 0) {
1061
- requestBody.limit = limit;
1062
- }
1063
- if (page !== void 0) {
1064
- requestBody.page = page;
1065
- }
1066
- if (proxyId && proxyId.length > 0) {
1067
- requestBody.proxy_id = proxyId;
1068
- }
1624
+ const requestBody = buildRequestBodyFor("get-proxy-list", params);
1069
1625
  const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.GET_PROXY_LIST}`, requestBody);
1070
1626
  if (response.data.code === 0) {
1071
1627
  return `Proxy list: ${JSON.stringify(response.data.data.list || response.data.data, null, 2)}`;
1072
1628
  }
1073
1629
  throw new Error(`Failed to get proxy list: ${response.data.msg}`);
1074
1630
  },
1075
- async deleteProxy({ proxyIds }) {
1076
- const response = await getApiClient().post(`${getLocalApiBase()}${API_ENDPOINTS.DELETE_PROXY}`, {
1077
- proxy_id: proxyIds
1078
- });
1631
+ async deleteProxy(params) {
1632
+ const response = await getApiClient().post(
1633
+ `${getLocalApiBase()}${API_ENDPOINTS.DELETE_PROXY}`,
1634
+ buildRequestBodyFor("delete-proxy", params)
1635
+ );
1636
+ const { proxy_id } = params;
1079
1637
  if (response.data.code === 0) {
1080
- return `Proxies deleted successfully: ${proxyIds.join(", ")}`;
1638
+ return `Proxies deleted successfully: ${proxy_id.join(", ")}`;
1081
1639
  }
1082
1640
  throw new Error(`Failed to delete proxies: ${response.data.msg}`);
1083
1641
  }
@@ -1131,7 +1689,7 @@ var import_path = __toESM(require("path"));
1131
1689
  var import_os = __toESM(require("os"));
1132
1690
 
1133
1691
  // ../core/src/utils/browserBase.ts
1134
- var import_playwright = require("playwright");
1692
+ var import_playwright_core = require("playwright-core");
1135
1693
  var BrowserBase = class {
1136
1694
  browser;
1137
1695
  page;
@@ -1166,7 +1724,7 @@ var BrowserBase = class {
1166
1724
  }
1167
1725
  }
1168
1726
  async connectBrowserWithWs(wsUrl) {
1169
- this.browser = await import_playwright.chromium.connectOverCDP(wsUrl);
1727
+ this.browser = await import_playwright_core.chromium.connectOverCDP(wsUrl);
1170
1728
  const defaultContext = this.browser.contexts()[0];
1171
1729
  this.page = defaultContext.pages()[0];
1172
1730
  await this.page.bringToFront().catch((error) => {
@@ -1242,9 +1800,9 @@ var userProxyConfigSchema = import_zod.z.object({
1242
1800
  proxy_type: import_zod.z.enum(["http", "https", "socks5", "no_proxy"]).optional(),
1243
1801
  proxy_host: import_zod.z.string().optional().describe("The proxy host of the browser, eg: 127.0.0.1"),
1244
1802
  proxy_port: import_zod.z.string().optional().describe("The proxy port of the browser, eg: 8080"),
1245
- proxy_user: import_zod.z.string().optional().describe("The proxy user of the browser, eg: user"),
1246
- proxy_password: import_zod.z.string().optional().describe("The proxy password of the browser, eg: password"),
1247
- proxy_url: import_zod.z.string().optional().describe("The proxy url of the browser, eg: http://127.0.0.1:8080"),
1803
+ proxy_user: import_zod.z.string().optional().describe("The proxy user for proxy authentication, eg: user"),
1804
+ proxy_password: import_zod.z.string().optional().describe("The proxy password for proxy authentication, eg: password"),
1805
+ proxy_url: import_zod.z.string().optional().describe("This URL is used for dynamic proxy, only supports http/https/socks5 proxies. 1. By clicking this link, you can manually change the proxy IP address. 2. When multiple environments use the same proxy account, refreshing the IP will change the IP address of the same proxy account."),
1248
1806
  global_config: import_zod.z.enum(["0", "1"]).optional().describe("The global config of the browser, default is 0")
1249
1807
  }).describe("The user proxy config of the browser");
1250
1808
  var CHROME_VERSIONS = [
@@ -1285,9 +1843,10 @@ var CHROME_VERSIONS = [
1285
1843
  "142",
1286
1844
  "143",
1287
1845
  "144",
1288
- "ua_auto"
1846
+ "ua_auto",
1847
+ "latest"
1289
1848
  ];
1290
- var FIREFOX_VERSIONS = ["100", "107", "114", "120", "123", "126", "129", "132", "135", "138", "141", "144", "ua_auto"];
1849
+ var FIREFOX_VERSIONS = ["100", "107", "114", "120", "123", "126", "129", "132", "135", "138", "141", "144", "ua_auto", "latest"];
1291
1850
  var ALL_KERNEL_VERSIONS = [.../* @__PURE__ */ new Set([...CHROME_VERSIONS, ...FIREFOX_VERSIONS])];
1292
1851
  var browserKernelConfigSchema = import_zod.z.object({
1293
1852
  version: import_zod.z.union(
@@ -1642,14 +2201,21 @@ var mediaDevicesNumSchema = import_zod.z.object({
1642
2201
  videoinput_num: import_zod.z.enum(DEVICE_COUNT_VALUES).describe("Number of cameras, 1-9"),
1643
2202
  audiooutput_num: import_zod.z.enum(DEVICE_COUNT_VALUES).describe("Number of speakers, 1-9")
1644
2203
  }).describe("Device counts when media_devices=2: audioinput_num, videoinput_num, audiooutput_num each 1-9.");
2204
+ var platformAccountSchema = import_zod.z.object({
2205
+ domain_name: import_zod.z.string().min(1).describe("Platform domain name, eg: facebook.com"),
2206
+ login_user: import_zod.z.string().min(1).describe("Platform login user, e.g. shop username or login email"),
2207
+ password: import_zod.z.string().min(1).optional().describe("Optional platform account password"),
2208
+ fakey: import_zod.z.string().min(1).optional().describe("2FA key for online 2FA code generators")
2209
+ }).strict().optional().describe("Structured platform account metadata keyed by Postman field name platform_account.");
2210
+ var nonEmptyStringArraySchema = import_zod.z.array(import_zod.z.string()).nonempty();
1645
2211
  var fingerprintConfigSchema = import_zod.z.object({
1646
2212
  automatic_timezone: import_zod.z.enum(["0", "1"]).optional().describe("Auto timezone by IP: 0 custom, 1 (default) by IP"),
1647
2213
  timezone: import_zod.z.string().optional().describe("Timezone when automatic_timezone=0, e.g. Asia/Shanghai"),
1648
- location_switch: import_zod.z.enum(["0", "1"]).optional().describe("Location by IP: 0 custom, 1 (default) by IP"),
2214
+ location_switch: import_zod.z.enum(["0", "1"]).optional().describe("1: Generate location based on IP (default); 0: Specify location"),
1649
2215
  longitude: import_zod.z.number().min(-180).max(180).optional().describe("Custom longitude when location_switch=0, -180 to 180, up to 6 decimals"),
1650
2216
  latitude: import_zod.z.number().min(-90).max(90).optional().describe("Custom latitude when location_switch=0, -90 to 90, up to 6 decimals"),
1651
2217
  accuracy: import_zod.z.number().int().min(10).max(5e3).optional().describe("Location accuracy in meters when location_switch=0, 10-5000, default 1000"),
1652
- location: import_zod.z.enum(["ask", "allow", "block"]).optional().describe("Site location permission: ask (default), allow, block"),
2218
+ location: import_zod.z.enum(["ask", "allow", "block"]).optional().describe("When the website requests to obtain your current location, the support: ask (default), allow, block; ask: ask (default), the same as the prompt of ordinary browsers; allow: always allow the website to get the location; block: always block the website from getting the location."),
1653
2219
  language_switch: import_zod.z.enum(["0", "1"]).optional().describe("Language by IP country: 0 custom, 1 (default) by IP"),
1654
2220
  language: import_zod.z.array(import_zod.z.string()).optional().describe('Custom languages when language_switch=0, e.g. ["en-US", "zh-CN"]'),
1655
2221
  page_language_switch: import_zod.z.enum(["0", "1"]).optional().describe("Match UI language to language: 0 off, 1 (default) on; Chrome 109+ Win / 119+ macOS, v2.6.72+"),
@@ -1665,7 +2231,7 @@ var fingerprintConfigSchema = import_zod.z.object({
1665
2231
  webgl_image: import_zod.z.enum(["0", "1"]).optional().describe("WebGL image fingerprint: 0 default, 1 (default) add noise"),
1666
2232
  webgl_config: webglConfigSchema.optional().describe("Custom WebGL metadata when webgl=2. Must include unmasked_vendor and unmasked_renderer (non-empty). webgpu.webgpu_switch: 0 Disabled, 1 WebGL based, 2 Real. V2.6.8.1+"),
1667
2233
  flash: import_zod.z.enum(["block", "allow"]).optional().describe("Flash: block (default) or allow"),
1668
- webrtc: import_zod.z.enum(["disabled", "forward", "proxy", "local"]).optional().describe("WebRTC: disabled (default), forward, proxy, local"),
2234
+ webrtc: import_zod.z.enum(["disabled", "forward", "proxy", "local", "disableUDP"]).optional().describe("WebRTC: forward: forward, use proxy IP to cover real IP, used in proxy scene, more secure (need to upgrade to V2.6.8.6 or later version); proxy: replace, use proxy IP to cover real IP, used in proxy scene; local: real, the website will get the real IP; disabled: disabled (default), the website will not get the IP; disableUDP: disable UDP, disable non-proxy UDP traffic (only supported by Chrome kernel)."),
1669
2235
  audio: import_zod.z.enum(["0", "1"]).optional().describe("Audio fingerprint: 0 close, 1 (default) add noise"),
1670
2236
  do_not_track: import_zod.z.enum(["default", "true", "false"]).optional().describe("Do Not Track: default, true (open), false (close)"),
1671
2237
  hardware_concurrency: import_zod.z.enum(["2", "4", "6", "8", "16"]).optional().describe("CPU cores: 2, 4 (default if omitted), 6, 8, 16; omit to follow current computer"),
@@ -1680,7 +2246,7 @@ var fingerprintConfigSchema = import_zod.z.object({
1680
2246
  speech_switch: import_zod.z.enum(["0", "1"]).optional().describe("SpeechVoices: 0 use computer default, 1 replace with value. V3.11.10+"),
1681
2247
  mac_address_config: macAddressConfigSchema.optional().describe("MAC address: model 0/1/2, address when model=2. V4.3.9+"),
1682
2248
  gpu: import_zod.z.enum(["0", "1", "2"]).optional().describe("GPU: 0 follow Local settings - Hardware acceleration, 1 turn on, 2 turn off"),
1683
- browser_kernel_config: browserKernelConfigSchema.optional(),
2249
+ browser_kernel_config: browserKernelConfigSchema.optional().default({ "version": "latest", "type": "chrome" }),
1684
2250
  random_ua: randomUaConfigSchema.optional().describe("Random UA config; ignored when ua (custom UA) is provided."),
1685
2251
  tls_switch: import_zod.z.enum(["0", "1"]).optional().describe("TLS custom list: 0 (default) off, 1 on"),
1686
2252
  tls: import_zod.z.string().optional().refine(
@@ -1702,127 +2268,156 @@ var fingerprintConfigSchema = import_zod.z.object({
1702
2268
  }
1703
2269
  }
1704
2270
  }).describe("Fingerprint config (fingerprint_config). All fields optional. See AdsPower Local API fingerprint_config.");
2271
+ var createProxyItemSchema = import_zod.z.object({
2272
+ type: import_zod.z.enum(["http", "https", "ssh", "socks5"]).describe("Proxy type, support: http/https/ssh/socks5"),
2273
+ host: import_zod.z.string().describe("Proxy host, support: ipV4, ipV6, eg: 192.168.0.1"),
2274
+ port: import_zod.z.string().describe("Port, range: 0-65536, eg: 8000"),
2275
+ user: import_zod.z.string().optional().describe("Proxy username, eg: user12345678"),
2276
+ password: import_zod.z.string().optional().describe("Proxy password, eg: password"),
2277
+ proxy_url: import_zod.z.string().optional().describe("URL used to refresh the proxy, eg: https://www.baidu.com/"),
2278
+ remark: import_zod.z.string().optional().describe("Remark/description for the proxy"),
2279
+ ipchecker: import_zod.z.enum(["ip2location", "ipapi", "ipfoxy"]).optional().describe("IP checker.")
2280
+ }).strict();
1705
2281
  var schemas = {
1706
2282
  createBrowserSchema: import_zod.z.object({
1707
- groupId: import_zod.z.string().regex(/^\d+$/, "Group ID must be a numeric string").describe('The group id of the browser, must be a numeric string (e.g., "123"). You can use the get-group-list tool to get the group list or create a new group, use 0 for Ungrouped'),
2283
+ group_id: import_zod.z.string().regex(/^\d+$/, "Group ID must be a numeric string").describe('The group id of the browser, must be a numeric string (e.g., "123"). You can use the get-group-list tool to get the group list or create a new group, use 0 for Ungrouped'),
1708
2284
  username: import_zod.z.string().optional().describe("Platform account username"),
1709
2285
  password: import_zod.z.string().optional().describe("Platform account password"),
1710
- cookie: import_zod.z.string().optional().describe("Cookie data in JSON or Netscape format"),
2286
+ cookie: import_zod.z.string().optional().describe(`Cookie data in JSON array string or Netscape format, eg: '[{"domain":".baidu.com","expirationDate":1724188800,"name":"BAIDUID","value":"xxxxxxxxxx"}]'`),
1711
2287
  fakey: import_zod.z.string().optional().describe("2FA key for online 2FA code generators"),
1712
- name: import_zod.z.string().max(100).optional().describe("Account name, max 100 characters"),
1713
- platform: import_zod.z.string().optional().describe("Platform domain, eg: facebook.com"),
1714
- remark: import_zod.z.string().optional().describe("Remarks to describe the account. Maximum 1500 characters."),
1715
- userProxyConfig: userProxyConfigSchema.default({ proxy_soft: "no_proxy" }).describe("Proxy configuration. If proxyid is provided, proxyid takes priority and this field is ignored. Defaults to no_proxy when neither proxyid nor a custom proxy is needed."),
1716
- proxyid: import_zod.z.string().optional().describe("Proxy profile ID. Takes priority over userProxyConfig when provided."),
1717
- repeatConfig: import_zod.z.array(import_zod.z.union([import_zod.z.literal(0), import_zod.z.literal(2), import_zod.z.literal(3), import_zod.z.literal(4)])).optional().describe("Account deduplication settings (0, 2, 3, or 4)"),
1718
- ignoreCookieError: import_zod.z.enum(["0", "1"]).optional().describe("Handle cookie verification failures: 0 (default) return data as-is, 1 filter out incorrectly formatted cookies"),
2288
+ name: import_zod.z.string().max(100).optional().describe("Profile name, max 100 characters"),
2289
+ platform: import_zod.z.string().optional().describe("Platform domain, eg: facebook.com, The platform account is only applicable to single account platform settings. If you need to configure multiple account platforms, please use platform_account instead."),
2290
+ remark: import_zod.z.string().optional().describe("Remarks to describe the profile. Maximum 1500 characters."),
2291
+ user_proxy_config: userProxyConfigSchema.default({ proxy_soft: "no_proxy" }).describe("Proxy configuration. If proxyid is provided, proxyid takes priority and this field is ignored. Defaults to no_proxy when neither proxyid nor a custom proxy is needed."),
2292
+ proxyid: import_zod.z.string().optional().describe(" Already added proxy (proxy ID). user_proxy_config and proxyid cannot be empty at the same time. Takes priority over user_proxy_config when provided."),
2293
+ repeat_config: import_zod.z.array(import_zod.z.union([import_zod.z.literal(0), import_zod.z.literal(2), import_zod.z.literal(3), import_zod.z.literal(4)])).optional().describe("Account deduplication settings (0, 2, 3, or 4), 0: allow duplicate (default), 2: deduplicate by account and password, 3: deduplicate by cookie, 4: deduplicate by c_user (c_user is Facebook's unique identifier)"),
2294
+ ignore_cookie_error: import_zod.z.enum(["0", "1"]).optional().describe("Handle cookie verification failures: 0 (default) return data as-is, 1 filter out incorrectly formatted cookies"),
1719
2295
  tabs: import_zod.z.array(import_zod.z.string()).optional().describe('URLs to open on startup, eg: ["https://www.google.com"]'),
1720
2296
  ip: import_zod.z.string().optional().describe("IP address"),
1721
2297
  country: countryCodeSchema.optional().describe('Country/Region, ISO 3166-1 alpha-2 (lowercase). eg: "cn", "us"'),
1722
2298
  region: import_zod.z.string().optional().describe("Region"),
1723
2299
  city: import_zod.z.string().optional().describe("City"),
1724
- ipchecker: import_zod.z.enum(["ip2location", "ipapi"]).optional().describe("IP query channel"),
1725
- categoryId: import_zod.z.string().optional().describe("The category id of the browser, you can use the get-application-list tool to get the application list"),
1726
- profileTagIds: import_zod.z.array(import_zod.z.string()).max(30).optional().describe('Tag IDs to assign to the profile, max 30 tags per profile. Example: ["tag1","tag2"]'),
1727
- fingerprintConfig: fingerprintConfigSchema.optional().default({ random_ua: { ua_system_version: ["Windows"] } })
1728
- }),
2300
+ ipchecker: import_zod.z.enum(["ip2location", "ipapi", "ipfoxy"]).optional().describe("IP query channel"),
2301
+ category_id: import_zod.z.string().optional().describe("The category id of the browser, you can use the get-application-list tool to get the application list"),
2302
+ profile_tag_ids: import_zod.z.array(import_zod.z.string()).max(30).optional().describe('Tag IDs to assign to the profile, max 30 tags per profile. Example: ["tag1","tag2"]'),
2303
+ fingerprint_config: fingerprintConfigSchema.optional().default({ random_ua: { ua_system_version: ["Windows"] }, browser_kernel_config: { version: "latest", type: "chrome" } }),
2304
+ platform_account: platformAccountSchema
2305
+ }).strict(),
1729
2306
  updateBrowserSchema: import_zod.z.object({
1730
2307
  platform: import_zod.z.string().optional().describe("The platform of the browser, eg: facebook.com"),
1731
2308
  tabs: import_zod.z.array(import_zod.z.string()).optional().describe('The tabs of the browser, eg: ["https://www.google.com"]'),
1732
- cookie: import_zod.z.string().optional().describe("The cookie of the browser"),
2309
+ cookie: import_zod.z.string().optional().describe(`Cookie data in JSON array string or Netscape format, eg: '[{"domain":".baidu.com","expirationDate":1724188800,"name":"BAIDUID","value":"xxxxxxxxxx"}]'`),
1733
2310
  username: import_zod.z.string().optional().describe('The username of the browser, eg: "user"'),
1734
2311
  password: import_zod.z.string().optional().describe('The password of the browser, eg: "password"'),
1735
2312
  fakey: import_zod.z.string().optional().describe("Enter the 2FA-key"),
1736
- ignoreCookieError: import_zod.z.enum(["0", "1"]).optional().describe("Specifies how to handle the case when cookie validation fails."),
1737
- groupId: import_zod.z.string().optional().describe('The group id of the browser, must be a numeric string (e.g., "123"). You can use the get-group-list tool to get the group list or create a new group'),
2313
+ ignore_cookie_error: import_zod.z.enum(["0", "1"]).optional().describe("Specifies how to handle the case when cookie validation fails."),
2314
+ group_id: import_zod.z.string().optional().describe('The group id of the browser, must be a numeric string (e.g., "123"). You can use the get-group-list tool to get the group list or create a new group'),
1738
2315
  name: import_zod.z.string().max(100).optional().describe('The Profile name of the browser, eg: "My Browser"'),
1739
2316
  remark: import_zod.z.string().max(1500).optional().describe("Profile remarks, maximum 1500 characters"),
1740
2317
  country: countryCodeSchema.optional().describe('The country of the browser, ISO 3166-1 alpha-2 (lowercase). eg: "cn", "us"'),
1741
2318
  region: import_zod.z.string().optional().describe("The region of the browser"),
1742
2319
  city: import_zod.z.string().optional().describe("The city of the browser"),
2320
+ ipchecker: import_zod.z.enum(["ip2location", "ipapi", "ipfoxy"]).optional().describe("IP query channel"),
1743
2321
  ip: import_zod.z.string().optional().describe("The IP of the browser"),
1744
- categoryId: import_zod.z.string().optional().describe("The category id of the browser, you can use the get-application-list tool to get the application list"),
1745
- userProxyConfig: userProxyConfigSchema.optional(),
2322
+ category_id: import_zod.z.string().optional().describe("The category id of the browser, you can use the get-application-list tool to get the application list"),
2323
+ user_proxy_config: userProxyConfigSchema.optional(),
1746
2324
  proxyid: import_zod.z.string().optional().describe("Proxy ID"),
1747
- fingerprintConfig: fingerprintConfigSchema.optional(),
1748
- launchArgs: import_zod.z.string().optional().describe("Browser startup parameters"),
1749
- profileTagIds: import_zod.z.array(import_zod.z.string()).max(30).optional().describe('Tag IDs to set on the profile, max 30 tags per profile. Example: ["tag1","tag2"]'),
1750
- tagsUpdateType: import_zod.z.enum(["1", "2"]).optional().describe('How to apply profile_tag_ids: "1" (default) replace all existing tags; "2" append tags (truncated to 30 total if exceeded)'),
1751
- profileId: import_zod.z.string().describe("The profile id of the browser to update, it is required when you want to update the browser")
1752
- }),
1753
- openBrowserSchema: import_zod.z.object({
1754
- profileNo: import_zod.z.string().optional().describe("Priority will be given to user id when profile_id is filled."),
1755
- profileId: import_zod.z.string().describe("Unique profile ID, generated after creating profile. The profile id of the browser to open"),
1756
- ipTab: import_zod.z.enum(["0", "1"]).optional().describe("The ip tab of the browser, 0 is not use ip tab, 1 is use ip tab, default is 0"),
1757
- launchArgs: import_zod.z.string().optional().describe("The launch args of the browser, use chrome launch args, or vista url"),
1758
- clearCacheAfterClosing: import_zod.z.enum(["0", "1"]).optional().describe("The clear cache after closing of the browser, 0 is not clear cache after closing, 1 is clear cache after closing, default is 0"),
1759
- cdpMask: import_zod.z.enum(["0", "1"]).optional().describe("The cdp mask of the browser, 0 is not use cdp mask, 1 is use cdp mask, default is 0")
2325
+ fingerprint_config: fingerprintConfigSchema.optional(),
2326
+ launch_args: import_zod.z.string().optional().describe("Browser startup parameters"),
2327
+ profile_tag_ids: import_zod.z.array(import_zod.z.string()).max(30).optional().describe('Tag IDs to set on the profile, max 30 tags per profile. Example: ["tag1","tag2"]'),
2328
+ tags_update_type: import_zod.z.enum(["1", "2"]).optional().describe('How to apply profile_tag_ids: "1" (default) replace all existing tags; "2" append tags (truncated to 30 total if exceeded)'),
2329
+ profile_id: import_zod.z.string().describe("The profile id of the browser to update, it is required when you want to update the browser"),
2330
+ platform_account: platformAccountSchema
1760
2331
  }).strict(),
2332
+ openBrowserSchema: import_zod.z.object({
2333
+ profile_no: import_zod.z.string().optional().describe(
2334
+ "Profile serial number (environment number). At least one of profile_id or profile_no is required; if both are provided, profile_id takes priority (AdsPower API). "
2335
+ ),
2336
+ profile_id: import_zod.z.string().optional().describe(
2337
+ "Unique profile ID generated after creating a profile; identifies which browser to open. At least one of profile_id or profile_no is required; if both are provided, profile_id takes priority (AdsPower API). "
2338
+ ),
2339
+ ip_tab: import_zod.z.enum(["0", "1"]).optional().describe("The ip tab of the browser, 0 is not use ip tab, 1 is use ip tab, default is 0"),
2340
+ launch_args: import_zod.z.union([import_zod.z.string(), import_zod.z.array(import_zod.z.string())]).optional().describe('The launch args of the browser, use chrome launch args, eg: ["--window-position=400,0","--blink-settings=imagesEnabled=false", "--disable-notifications"]'),
2341
+ headless: import_zod.z.enum(["0", "1"]).optional().describe(
2342
+ 'Headless: "0" visible window, "1" headless. If omitted, the runtime may auto-set "1" when no graphical session is detected (Linux without DISPLAY/WAYLAND, or CI). Explicit "0"/"1" is always sent as-is.'
2343
+ ),
2344
+ last_opened_tabs: import_zod.z.enum(["0", "1"]).optional().describe("Whether to restore the last opened tabs."),
2345
+ proxy_detection: import_zod.z.enum(["0", "1"]).optional().describe("Whether to enable proxy detection."),
2346
+ password_filling: import_zod.z.enum(["0", "1"]).optional().describe("Whether to enable password auto-filling."),
2347
+ password_saving: import_zod.z.enum(["0", "1"]).optional().describe("Whether to enable password saving."),
2348
+ delete_cache: import_zod.z.enum(["0", "1"]).optional().describe("The clear cache after closing of the browser, 0 is not clear cache after closing, 1 is clear cache after closing, default is 0"),
2349
+ cdp_mask: import_zod.z.enum(["0", "1"]).optional().describe("The cdp mask of the browser, 0 is not use cdp mask, 1 is use cdp mask, default is 0"),
2350
+ device_scale: import_zod.z.string().optional().describe("Device scale factor passed to browser-profile/start.")
2351
+ }).strict().refine((data) => data.profile_id || data.profile_no, {
2352
+ message: "Either profile_id or profile_no must be provided"
2353
+ }),
1761
2354
  closeBrowserSchema: import_zod.z.object({
1762
- profileId: import_zod.z.string().optional().describe("The profile id of the browser to stop, either profileId or profileNo must be provided"),
1763
- profileNo: import_zod.z.string().optional().describe("The profile number of the browser to stop, priority will be given to profileId when profileId is filled")
1764
- }).refine((data) => data.profileId || data.profileNo, {
1765
- message: "Either profileId or profileNo must be provided"
2355
+ profile_id: import_zod.z.string().optional().describe("The profile id of the browser to stop, either profile_id or profile_no must be provided"),
2356
+ profile_no: import_zod.z.string().optional().describe("The profile number of the browser to stop, priority will be given to profile_id when profile_id is filled")
2357
+ }).strict().refine((data) => data.profile_id || data.profile_no, {
2358
+ message: "Either profile_id or profile_no must be provided"
1766
2359
  }),
1767
2360
  deleteBrowserSchema: import_zod.z.object({
1768
- profileIds: import_zod.z.array(import_zod.z.string()).describe("The profile ids of the browsers to delete, it is required when you want to delete the browser")
2361
+ profile_id: import_zod.z.array(import_zod.z.string()).describe("The profile ids of the browsers to delete, it is required when you want to delete the browser")
1769
2362
  }).strict(),
1770
2363
  getBrowserListSchema: import_zod.z.object({
1771
- groupId: import_zod.z.string().regex(/^\d+$/, "Group ID must be a numeric string").optional().describe("Query by group ID; searches all groups if empty"),
1772
- limit: import_zod.z.number().optional().describe("Profiles per page. Number of profiles returned per page, range 1 ~ 200, default is 50"),
1773
- page: import_zod.z.number().optional().describe("Page number for results, default is 1"),
1774
- profileId: import_zod.z.array(import_zod.z.string()).optional().describe('Query by profile ID. Example: ["h1yynkm","h1yynks"]'),
1775
- profileNo: import_zod.z.array(import_zod.z.string()).optional().describe('Query by profile number. Example: ["123","124"]'),
1776
- sortType: import_zod.z.enum(["profile_no", "last_open_time", "created_time"]).optional().describe("Sort results by: profile_no, last_open_time, or created_time"),
1777
- sortOrder: import_zod.z.enum(["asc", "desc"]).optional().describe('Sort order: "asc" (ascending) or "desc" (descending)'),
1778
- tag_ids: import_zod.z.array(import_zod.z.string()).optional().describe('Tag IDs to filter profiles by tags. Example: ["tag1","tag2"]'),
2364
+ group_id: import_zod.z.string().regex(/^\d+$/, "Group ID must be a numeric string").optional().describe("Query by group ID; searches all groups if empty"),
2365
+ limit: import_zod.z.number().min(1).max(200).optional().describe("Profiles per page. Number of profiles returned per page, range 1 ~ 200, default is 50"),
2366
+ page: import_zod.z.number().min(1).optional().describe("Page number for results, default is 1"),
2367
+ profile_id: nonEmptyStringArraySchema.optional().describe('Query by profile ID. Example: ["h1yynkm","h1yynks"]'),
2368
+ profile_no: nonEmptyStringArraySchema.optional().describe('Query by profile number. Example: ["123","124"]'),
2369
+ sort_type: import_zod.z.enum(["profile_no", "last_open_time", "created_time"]).optional().describe("Sort results by: profile_no, last_open_time, or created_time"),
2370
+ sort_order: import_zod.z.enum(["asc", "desc"]).optional().describe('Sort order: "asc" (ascending) or "desc" (descending)'),
2371
+ tag_ids: nonEmptyStringArraySchema.optional().describe('Tag IDs to filter profiles by tags. Example: ["tag1","tag2"]'),
1779
2372
  tags_filter: import_zod.z.enum(["include", "exclude"]).optional().describe('Tag matching mode: "include" (default) matches profiles with any of the tags, "exclude" matches profiles without the tags'),
1780
2373
  name: import_zod.z.string().optional().describe("Profile name keyword to search for"),
1781
2374
  name_filter: import_zod.z.enum(["include", "exclude"]).optional().describe('Name matching mode: "include" (default) matches profiles containing the name keyword, "exclude" matches profiles not containing the name keyword')
1782
2375
  }).strict(),
1783
2376
  moveBrowserSchema: import_zod.z.object({
1784
- groupId: import_zod.z.string().regex(/^\d+$/, "Group ID must be a numeric string").describe('The target group id, must be a numeric string (e.g., "123"). You can use the get-group-list tool to get the group list'),
1785
- userIds: import_zod.z.array(import_zod.z.string()).describe("The browser Profile ids to move")
2377
+ group_id: import_zod.z.string().regex(/^\d+$/, "Group ID must be a numeric string").describe('The target group id, must be a numeric string (e.g., "123"). You can use the get-group-list tool to get the group list'),
2378
+ user_ids: import_zod.z.array(import_zod.z.string()).describe("The browser Profile ids to move")
1786
2379
  }).strict(),
1787
2380
  getProfileCookiesSchema: import_zod.z.object({
1788
- profileId: import_zod.z.string().optional().describe("The profile id, either profileId or profileNo must be provided"),
1789
- profileNo: import_zod.z.string().optional().describe("The profile number, priority will be given to profileId when profileId is filled")
1790
- }).refine((data) => data.profileId || data.profileNo, {
1791
- message: "Either profileId or profileNo must be provided"
2381
+ profile_id: import_zod.z.string().optional().describe("The profile id, either profile_id or profile_no must be provided"),
2382
+ profile_no: import_zod.z.string().optional().describe("The profile number, priority will be given to profile_id when profile_id is filled")
2383
+ }).strict().refine((data) => data.profile_id || data.profile_no, {
2384
+ message: "Either profile_id or profile_no must be provided"
1792
2385
  }),
1793
2386
  getProfileUaSchema: import_zod.z.object({
1794
- profileId: import_zod.z.array(import_zod.z.string()).optional().describe("The profile id array, either profileId or profileNo must be provided"),
1795
- profileNo: import_zod.z.array(import_zod.z.string()).optional().describe("The profile number array, priority will be given to profileId when profileId is filled")
1796
- }).refine((data) => data.profileId && data.profileId.length > 0 || data.profileNo && data.profileNo.length > 0, {
1797
- message: "Either profileId or profileNo must be provided with at least one element"
2387
+ profile_id: nonEmptyStringArraySchema.optional().describe("The profile id array, either profile_id or profile_no must be provided"),
2388
+ profile_no: nonEmptyStringArraySchema.optional().describe("The profile number array, priority will be given to profile_id when profile_id is filled")
2389
+ }).strict().refine((data) => data.profile_id && data.profile_id.length > 0 || data.profile_no && data.profile_no.length > 0, {
2390
+ message: "Either profile_id or profile_no must be provided with at least one element"
1798
2391
  }),
1799
2392
  closeAllProfilesSchema: import_zod.z.object({}).strict(),
1800
2393
  newFingerprintSchema: import_zod.z.object({
1801
- profileId: import_zod.z.array(import_zod.z.string()).optional().describe("The profile id array, either profileId or profileNo must be provided"),
1802
- profileNo: import_zod.z.array(import_zod.z.string()).optional().describe("The profile number array, priority will be given to profileId when profileId is filled")
1803
- }).strict(),
2394
+ profile_id: nonEmptyStringArraySchema.optional().describe("The profile id array, either profile_id or profile_no must be provided"),
2395
+ profile_no: nonEmptyStringArraySchema.optional().describe("The profile number array, priority will be given to profile_id when profile_id is filled")
2396
+ }).strict().refine((data) => data.profile_id && data.profile_id.length > 0 || data.profile_no && data.profile_no.length > 0, {
2397
+ message: "Either profile_id or profile_no must be provided with at least one element"
2398
+ }),
1804
2399
  deleteCacheV2Schema: import_zod.z.object({
1805
- profileIds: import_zod.z.array(import_zod.z.string()).describe("The profile ids array, it is required"),
2400
+ profile_id: import_zod.z.array(import_zod.z.string()).describe("The profile ids array, it is required"),
1806
2401
  type: import_zod.z.array(import_zod.z.enum(["local_storage", "indexeddb", "extension_cache", "cookie", "history", "image_file"])).describe("Types of cache to clear, it is required")
1807
2402
  }).strict(),
1808
2403
  shareProfileSchema: import_zod.z.object({
1809
- profileIds: import_zod.z.array(import_zod.z.string()).describe("The profile ids array, it is required"),
2404
+ profile_id: import_zod.z.array(import_zod.z.string()).describe("The profile ids array, it is required"),
1810
2405
  receiver: import_zod.z.string().describe("Receiver's account email or phone number (no area code), it is required"),
1811
- shareType: import_zod.z.number().int().optional().describe("Share type: 1 for email (default), 2 for phone number"),
2406
+ share_type: import_zod.z.number().int().optional().describe("Share type: 1 for email (default), 2 for phone number"),
1812
2407
  content: import_zod.z.array(import_zod.z.enum(["name", "proxy", "remark", "tabs"])).optional().describe("Shared content")
1813
2408
  }).strict(),
1814
2409
  createGroupSchema: import_zod.z.object({
1815
- groupName: import_zod.z.string().describe("The name of the group to create"),
2410
+ group_name: import_zod.z.string().describe("The name of the group to create"),
1816
2411
  remark: import_zod.z.string().optional().describe("The remark of the group")
1817
2412
  }).strict(),
1818
2413
  updateGroupSchema: import_zod.z.object({
1819
- groupId: import_zod.z.string().regex(/^\d+$/, "Group ID must be a numeric string").describe('The id of the group to update, must be a numeric string (e.g., "123"). You can use the get-group-list tool to get the group list'),
1820
- groupName: import_zod.z.string().describe("The new name of the group"),
2414
+ group_id: import_zod.z.string().regex(/^\d+$/, "Group ID must be a numeric string").describe('The id of the group to update, must be a numeric string (e.g., "123"). You can use the get-group-list tool to get the group list'),
2415
+ group_name: import_zod.z.string().describe("The new name of the group"),
1821
2416
  remark: import_zod.z.string().nullable().optional().describe("The new remark of the group")
1822
2417
  }).strict(),
1823
2418
  getGroupListSchema: import_zod.z.object({
1824
- groupName: import_zod.z.string().optional().describe("The name of the group to search, use like to search"),
1825
- size: import_zod.z.number().optional().describe("The size of the page, max is 100, default is 10"),
2419
+ group_name: import_zod.z.string().optional().describe("The name of the group to search, use like to search"),
2420
+ page_size: import_zod.z.number().optional().describe("The size of the page, max is 100, default is 10"),
1826
2421
  page: import_zod.z.number().optional().describe("The page of the group, default is 1")
1827
2422
  }).strict(),
1828
2423
  getApplicationListSchema: import_zod.z.object({
@@ -1831,46 +2426,38 @@ var schemas = {
1831
2426
  limit: import_zod.z.number().min(1).max(100).optional().describe("Default 1, how many values are returned per page, range 1 to 100")
1832
2427
  }).strict(),
1833
2428
  getBrowserActiveSchema: import_zod.z.object({
1834
- profileId: import_zod.z.string().optional().describe("The profile id, either profileId or profileNo must be provided"),
1835
- profileNo: import_zod.z.string().optional().describe("The profile number, priority will be given to profileId when profileId is filled")
1836
- }).refine((data) => data.profileId || data.profileNo, {
1837
- message: "Either profileId or profileNo must be provided"
2429
+ profile_id: import_zod.z.string().optional().describe("The profile id, either profile_id or profile_no must be provided"),
2430
+ profile_no: import_zod.z.string().optional().describe("The profile number, priority will be given to profile_id when profile_id is filled")
2431
+ }).strict().refine((data) => data.profile_id || data.profile_no, {
2432
+ message: "Either profile_id or profile_no must be provided"
1838
2433
  }),
1839
2434
  getCloudActiveSchema: import_zod.z.object({
1840
- userIds: import_zod.z.string().describe("Profile IDs string to check (split by comma, max 100 per request). Unique profile ID, generated after creating the profile.")
1841
- }).refine((data) => data.userIds.split(",").length <= 100, {
2435
+ user_ids: import_zod.z.string().describe("Profile IDs string to check (split by comma, max 100 per request). Unique profile ID, generated after creating the profile.")
2436
+ }).refine((data) => data.user_ids.split(",").length <= 100, {
1842
2437
  message: "The number of profile ids is too many, the maximum is 100"
1843
2438
  }),
1844
- createProxySchema: import_zod.z.object({
1845
- proxies: import_zod.z.array(import_zod.z.object({
1846
- type: import_zod.z.enum(["http", "https", "ssh", "socks5"]).describe("Proxy type, support: http/https/ssh/socks5"),
1847
- host: import_zod.z.string().describe("Proxy host, support: ipV4, ipV6, eg: 192.168.0.1"),
1848
- port: import_zod.z.string().describe("Port, range: 0-65536, eg: 8000"),
1849
- user: import_zod.z.string().optional().describe("Proxy username, eg: user12345678"),
1850
- password: import_zod.z.string().optional().describe("Proxy password, eg: password"),
1851
- proxy_url: import_zod.z.string().optional().describe("URL used to refresh the proxy, eg: https://www.baidu.com/"),
1852
- remark: import_zod.z.string().optional().describe("Remark/description for the proxy"),
1853
- ipchecker: import_zod.z.enum(["ipinfo", "ip2location", "ipapi", "ipfoxy"]).optional().describe("IP checker.")
1854
- }).strict()).describe("Array of proxy configurations to create")
2439
+ createProxySchema: import_zod.z.array(createProxyItemSchema).describe("Top-level array of proxy configurations to create"),
2440
+ createProxyMcpSchema: import_zod.z.object({
2441
+ proxies: import_zod.z.array(createProxyItemSchema).describe("Compatibility wrapper for MCP create-proxy input. Core and CLI accept a top-level array.")
1855
2442
  }).strict(),
1856
2443
  updateProxySchema: import_zod.z.object({
1857
- proxyId: import_zod.z.string().describe("The unique id after the proxy is added"),
2444
+ proxy_id: import_zod.z.string().describe("The unique id after the proxy is added"),
1858
2445
  type: import_zod.z.enum(["http", "https", "ssh", "socks5"]).optional().describe("Proxy type, support: http/https/ssh/socks5"),
1859
2446
  host: import_zod.z.string().optional().describe("Proxy host, support: ipV4, ipV6, eg: 192.168.0.1"),
1860
2447
  port: import_zod.z.string().optional().describe("Port, range: 0-65536, eg: 8000"),
1861
2448
  user: import_zod.z.string().optional().describe("Proxy username, eg: user12345678"),
1862
2449
  password: import_zod.z.string().optional().describe("Proxy password, eg: password"),
1863
- proxyUrl: import_zod.z.string().optional().describe("URL used to refresh the proxy, eg: https://www.baidu.com/"),
2450
+ proxy_url: import_zod.z.string().optional().describe("URL used to refresh the proxy, eg: https://www.baidu.com/"),
1864
2451
  remark: import_zod.z.string().optional().describe("Remark/description for the proxy"),
1865
2452
  ipchecker: import_zod.z.enum(["ip2location", "ipapi", "ipfoxy"]).optional().describe("IP checker.")
1866
2453
  }).strict(),
1867
2454
  getProxyListSchema: import_zod.z.object({
1868
2455
  limit: import_zod.z.number().optional().describe("Profiles per page. Number of proxies returned per page, range 1 ~ 200, default is 50"),
1869
2456
  page: import_zod.z.number().optional().describe("Page number for results, default is 1"),
1870
- proxyId: import_zod.z.array(import_zod.z.string()).optional().describe('Query by proxy ID. Example: ["proxy1","proxy2"]')
2457
+ proxy_id: nonEmptyStringArraySchema.optional().describe('Query by proxy ID. Single request can pass up to 100 proxy IDs. Example: ["proxy1","proxy2"]')
1871
2458
  }).strict(),
1872
2459
  deleteProxySchema: import_zod.z.object({
1873
- proxyIds: import_zod.z.array(import_zod.z.string()).describe("The proxy ids of the proxies to delete, it is required when you want to delete the proxy. The maximum is 100. ")
2460
+ proxy_id: import_zod.z.array(import_zod.z.string()).describe("The proxy ids of the proxies to delete, it is required when you want to delete the proxy. The maximum is 100. ")
1874
2461
  }).strict(),
1875
2462
  getTagListSchema: import_zod.z.object({
1876
2463
  ids: import_zod.z.array(import_zod.z.string()).optional().describe('Tag IDs to query, max 100 per request. Example: ["tag1","tag2"]'),
@@ -1954,155 +2541,241 @@ var schemas = {
1954
2541
  var STATELESS_HANDLERS = {
1955
2542
  "open-browser": {
1956
2543
  fn: browserHandlers.openBrowser,
1957
- description: "Open the browser, both environment and profile mean browser"
2544
+ description: buildCliCommandDescription(
2545
+ "open-browser",
2546
+ "Open the browser, both environment and profile mean browser"
2547
+ )
1958
2548
  },
1959
2549
  "close-browser": {
1960
2550
  fn: browserHandlers.closeBrowser,
1961
- description: "Close the browser"
2551
+ description: buildCliCommandDescription("close-browser", "Close the browser")
1962
2552
  },
1963
2553
  "create-browser": {
1964
2554
  fn: browserHandlers.createBrowser,
1965
- description: "Create a browser"
2555
+ description: buildCliCommandDescription("create-browser", "Create a browser")
1966
2556
  },
1967
2557
  "update-browser": {
1968
2558
  fn: browserHandlers.updateBrowser,
1969
- description: "Update the browser"
2559
+ description: buildCliCommandDescription("update-browser", "Update the browser")
1970
2560
  },
1971
2561
  "delete-browser": {
1972
2562
  fn: browserHandlers.deleteBrowser,
1973
- description: "Delete the browser"
2563
+ description: buildCliCommandDescription("delete-browser", "Delete the browser")
1974
2564
  },
1975
2565
  "get-browser-list": {
1976
2566
  fn: browserHandlers.getBrowserList,
1977
- description: "Get the list of browsers"
2567
+ description: buildCliCommandDescription("get-browser-list", "Get the list of browsers")
1978
2568
  },
1979
2569
  "get-opened-browser": {
1980
2570
  fn: browserHandlers.getOpenedBrowser,
1981
- description: "Get the list of opened browsers"
2571
+ description: buildCliCommandDescription("get-opened-browser", "Get the list of opened browsers")
1982
2572
  },
1983
2573
  "move-browser": {
1984
2574
  fn: browserHandlers.moveBrowser,
1985
- description: "Move browsers to a group"
2575
+ description: buildCliCommandDescription("move-browser", "Move browsers to a group")
1986
2576
  },
1987
2577
  "get-profile-cookies": {
1988
2578
  fn: browserHandlers.getProfileCookies,
1989
- description: "Query and return cookies of the specified profile. Only one profile can be queried per request."
2579
+ description: buildCliCommandDescription(
2580
+ "get-profile-cookies",
2581
+ "Query and return cookies of the specified profile. Only one profile can be queried per request."
2582
+ )
1990
2583
  },
1991
2584
  "get-profile-ua": {
1992
2585
  fn: browserHandlers.getProfileUa,
1993
- description: "Query and return the User-Agent of specified profiles. Up to 10 profiles can be queried per request."
2586
+ description: buildCliCommandDescription(
2587
+ "get-profile-ua",
2588
+ "Query and return the User-Agent of specified profiles. Up to 10 profiles can be queried per request."
2589
+ )
1994
2590
  },
1995
2591
  "close-all-profiles": {
1996
2592
  fn: browserHandlers.closeAllProfiles,
1997
- description: "Close all opened profiles on the current device"
2593
+ description: buildCliCommandDescription(
2594
+ "close-all-profiles",
2595
+ "Close all opened profiles on the current device"
2596
+ )
1998
2597
  },
1999
2598
  "new-fingerprint": {
2000
2599
  fn: browserHandlers.newFingerprint,
2001
- description: "Generate a new fingerprint for specified profiles. Up to 10 profiles are supported per request."
2600
+ description: buildCliCommandDescription(
2601
+ "new-fingerprint",
2602
+ "Generate a new fingerprint for specified profiles. Up to 10 profiles are supported per request."
2603
+ )
2002
2604
  },
2003
2605
  "delete-cache-v2": {
2004
2606
  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."
2607
+ description: buildCliCommandDescription(
2608
+ "delete-cache-v2",
2609
+ "Clear local cache of specific profiles.For account security, please ensure that there are no open browsers on the device when using this interface."
2610
+ )
2006
2611
  },
2007
2612
  "share-profile": {
2008
2613
  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."
2614
+ description: buildCliCommandDescription(
2615
+ "share-profile",
2616
+ "Share profiles via account email or phone number. The maximum number of profiles that can be shared at one time is 200."
2617
+ )
2010
2618
  },
2011
2619
  "get-browser-active": {
2012
2620
  fn: browserHandlers.getBrowserActive,
2013
- description: "Get active browser profile information"
2621
+ description: buildCliCommandDescription("get-browser-active", "Get active browser profile information")
2014
2622
  },
2015
2623
  "get-cloud-active": {
2016
2624
  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."'
2625
+ description: buildCliCommandDescription(
2626
+ "get-cloud-active",
2627
+ '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."'
2628
+ )
2018
2629
  },
2019
2630
  "create-group": {
2020
2631
  fn: groupHandlers.createGroup,
2021
- description: "Create a browser group"
2632
+ description: buildCliCommandDescription("create-group", "Create a browser group")
2022
2633
  },
2023
2634
  "update-group": {
2024
2635
  fn: groupHandlers.updateGroup,
2025
- description: "Update the browser group"
2636
+ description: buildCliCommandDescription("update-group", "Update the browser group")
2026
2637
  },
2027
2638
  "get-group-list": {
2028
2639
  fn: groupHandlers.getGroupList,
2029
- description: "Get the list of groups"
2640
+ description: buildCliCommandDescription("get-group-list", "Get the list of groups")
2030
2641
  },
2031
2642
  "check-status": {
2032
2643
  fn: applicationHandlers.checkStatus,
2033
- description: "Check the availability of the current device API interface (Connection Status)"
2644
+ description: buildCliCommandDescription(
2645
+ "check-status",
2646
+ "Check the availability of the current device API interface (Connection Status)"
2647
+ )
2034
2648
  },
2035
2649
  "get-application-list": {
2036
2650
  fn: applicationHandlers.getApplicationList,
2037
- description: "Get the list of applications (categories)"
2651
+ description: buildCliCommandDescription(
2652
+ "get-application-list",
2653
+ "Get the list of applications (categories)"
2654
+ )
2038
2655
  },
2039
2656
  "create-proxy": {
2040
2657
  fn: proxyHandlers.createProxy,
2041
- description: "Create the proxy"
2658
+ description: buildCliCommandDescription("create-proxy", "Create the proxy")
2042
2659
  },
2043
2660
  "update-proxy": {
2044
2661
  fn: proxyHandlers.updateProxy,
2045
- description: "Update the proxy"
2662
+ description: buildCliCommandDescription("update-proxy", "Update the proxy")
2046
2663
  },
2047
2664
  "get-proxy-list": {
2048
2665
  fn: proxyHandlers.getProxyList,
2049
- description: "Get the list of proxies"
2666
+ description: buildCliCommandDescription("get-proxy-list", "Get the list of proxies")
2050
2667
  },
2051
2668
  "delete-proxy": {
2052
2669
  fn: proxyHandlers.deleteProxy,
2053
- description: "Delete the proxy"
2670
+ description: buildCliCommandDescription("delete-proxy", "Delete the proxy")
2054
2671
  },
2055
2672
  "get-tag-list": {
2056
2673
  fn: tagHandlers.getTagList,
2057
- description: "Get the list of browser tags"
2674
+ description: buildCliCommandDescription("get-tag-list", "Get the list of browser tags")
2058
2675
  },
2059
2676
  "create-tag": {
2060
2677
  fn: tagHandlers.createTag,
2061
- description: "Create browser tags (batch supported)"
2678
+ description: buildCliCommandDescription("create-tag", "Create browser tags (batch supported)")
2062
2679
  },
2063
2680
  "update-tag": {
2064
2681
  fn: tagHandlers.updateTag,
2065
- description: "Update browser tags (batch supported)"
2682
+ description: buildCliCommandDescription("update-tag", "Update browser tags (batch supported)")
2066
2683
  },
2067
2684
  "delete-tag": {
2068
2685
  fn: tagHandlers.deleteTag,
2069
- description: "Delete browser tags"
2686
+ description: buildCliCommandDescription("delete-tag", "Delete browser tags")
2070
2687
  },
2071
2688
  "download-kernel": {
2072
2689
  fn: kernelHandlers.downloadKernel,
2073
- description: "Download or update a browser kernel version"
2690
+ description: buildCliCommandDescription(
2691
+ "download-kernel",
2692
+ "Download or update a browser kernel version"
2693
+ )
2074
2694
  },
2075
2695
  "get-kernel-list": {
2076
2696
  fn: kernelHandlers.getKernelList,
2077
- description: "Get browser kernel list by type or all"
2697
+ description: buildCliCommandDescription("get-kernel-list", "Get browser kernel list by type or all")
2078
2698
  },
2079
2699
  "update-patch": {
2080
2700
  fn: patchHandlers.updatePatch,
2081
- description: "Update AdsPower to latest patch version"
2701
+ description: buildCliCommandDescription("update-patch", "Update AdsPower to latest patch version")
2082
2702
  }
2083
2703
  };
2084
2704
  var SINGLE_PROFILE_ID_COMMANDS = {
2085
- "open-browser": "profileId",
2086
- "close-browser": "profileId",
2087
- "get-profile-cookies": "profileId",
2088
- "get-browser-active": "profileId"
2705
+ "open-browser": "profile_id",
2706
+ "close-browser": "profile_id",
2707
+ "get-profile-cookies": "profile_id",
2708
+ "get-browser-active": "profile_id"
2089
2709
  };
2090
2710
  var SINGLE_PROFILE_ID_ARRAY_COMMANDS = ["get-profile-ua", "new-fingerprint"];
2711
+ function resolveStatelessCommandArgs(commandName, params) {
2712
+ let args = {};
2713
+ if (!params) {
2714
+ return { ok: true, args };
2715
+ }
2716
+ const trimmed = params.trim();
2717
+ if (trimmed.startsWith("{")) {
2718
+ try {
2719
+ args = JSON.parse(params);
2720
+ return { ok: true, args };
2721
+ } catch {
2722
+ return { ok: false, error: "Invalid JSON for command args" };
2723
+ }
2724
+ }
2725
+ if (SINGLE_PROFILE_ID_COMMANDS[commandName]) {
2726
+ if (!isNaN(Number(trimmed))) {
2727
+ return { ok: true, args: { profile_no: trimmed } };
2728
+ }
2729
+ return { ok: true, args: { profile_id: trimmed } };
2730
+ }
2731
+ if (SINGLE_PROFILE_ID_ARRAY_COMMANDS.includes(commandName)) {
2732
+ if (!isNaN(Number(trimmed))) {
2733
+ return { ok: true, args: { profile_no: [trimmed] } };
2734
+ }
2735
+ return { ok: true, args: { profile_id: [trimmed] } };
2736
+ }
2737
+ try {
2738
+ args = JSON.parse(params);
2739
+ return { ok: true, args };
2740
+ } catch {
2741
+ return {
2742
+ ok: false,
2743
+ error: `Command requires JSON args (e.g. '{"key":"value"}') or use a supported shorthand`
2744
+ };
2745
+ }
2746
+ }
2747
+
2748
+ // src/startConfig.ts
2749
+ var MISSING_API_KEY_ERROR = "error: required option '-k, --api-key <apiKey>' not specified";
2750
+ function resolveStartApiKey(optionApiKey, env = process.env) {
2751
+ if (optionApiKey) {
2752
+ return {
2753
+ ok: true,
2754
+ apiKey: optionApiKey
2755
+ };
2756
+ }
2757
+ if (env.ADS_API_KEY) {
2758
+ return {
2759
+ ok: true,
2760
+ apiKey: env.ADS_API_KEY
2761
+ };
2762
+ }
2763
+ return {
2764
+ ok: false,
2765
+ error: MISSING_API_KEY_ERROR
2766
+ };
2767
+ }
2091
2768
 
2092
2769
  // src/index.ts
2093
2770
  var program = new import_commander.Command();
2094
2771
  program.name("adspower-browser").description("CLI and runtime for adspower-browser").version(VERSION);
2095
2772
  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", "");
2773
+ const resolvedApiKey = resolveStartApiKey(options.apiKey, process.env);
2774
+ if (!resolvedApiKey.ok) {
2775
+ logError(resolvedApiKey.error);
2776
+ process.exit(1);
2105
2777
  }
2778
+ store.setStoreValue("apiKey", resolvedApiKey.apiKey);
2106
2779
  if (options.baseUrl) {
2107
2780
  store.setStoreValue("baseUrl", options.baseUrl);
2108
2781
  }
@@ -2132,34 +2805,12 @@ for (const cmd of Object.keys(STATELESS_HANDLERS)) {
2132
2805
  }
2133
2806
  const { apiKey, port } = getApiKeyAndPort(options);
2134
2807
  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
- }
2161
- }
2808
+ const resolved = resolveStatelessCommandArgs(command.name(), params);
2809
+ if (!resolved.ok) {
2810
+ logError(resolved.error);
2811
+ return;
2162
2812
  }
2813
+ const args = resolved.args;
2163
2814
  logSuccess(`Executing command: ${command.name()}, params: ${JSON.stringify(args)}`);
2164
2815
  const loading = createLoading(`Executing ${command.name()}...`);
2165
2816
  try {