@hangox/mg-cli 1.0.8 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli/index.ts
4
- import { Command as Command9 } from "commander";
4
+ import { Command as Command12 } from "commander";
5
5
 
6
6
  // src/cli/commands/server.ts
7
7
  import { Command } from "commander";
@@ -340,6 +340,12 @@ function extractSpaceInfo(node) {
340
340
  width: roundToOneDecimal(typeof node.width === "number" ? node.width : 0),
341
341
  height: roundToOneDecimal(typeof node.height === "number" ? node.height : 0)
342
342
  };
343
+ if (typeof node.absoluteX === "number") {
344
+ result.absoluteX = roundToOneDecimal(node.absoluteX);
345
+ }
346
+ if (typeof node.absoluteY === "number") {
347
+ result.absoluteY = roundToOneDecimal(node.absoluteY);
348
+ }
343
349
  if (node.children && Array.isArray(node.children) && node.children.length > 0) {
344
350
  result.children = node.children.map((child) => extractSpaceInfo(child));
345
351
  }
@@ -365,6 +371,7 @@ var ErrorNames = {
365
371
  ["E015" /* SERVER_START_FAILED */]: "SERVER_START_FAILED",
366
372
  ["E016" /* SERVER_ALREADY_RUNNING */]: "SERVER_ALREADY_RUNNING",
367
373
  ["E017" /* CONNECTION_LOST */]: "CONNECTION_LOST",
374
+ ["E018" /* NO_EXTENSION_CONNECTED */]: "NO_EXTENSION_CONNECTED",
368
375
  ["E099" /* UNKNOWN_ERROR */]: "UNKNOWN_ERROR"
369
376
  };
370
377
  var ErrorMessages = {
@@ -385,6 +392,7 @@ var ErrorMessages = {
385
392
  ["E015" /* SERVER_START_FAILED */]: "\u81EA\u52A8\u542F\u52A8 Server \u5931\u8D25",
386
393
  ["E016" /* SERVER_ALREADY_RUNNING */]: "Server \u5DF2\u5728\u8FD0\u884C\u4E2D",
387
394
  ["E017" /* CONNECTION_LOST */]: "\u8FDE\u63A5\u65AD\u5F00",
395
+ ["E018" /* NO_EXTENSION_CONNECTED */]: "\u6CA1\u6709 Chrome \u6269\u5C55\u8FDE\u63A5\u5230 Server\u3002\u8BF7\u786E\u4FDD\u6D4F\u89C8\u5668\u5DF2\u6253\u5F00\u5E76\u5B89\u88C5\u4E86 MG Plugin",
388
396
  ["E099" /* UNKNOWN_ERROR */]: "\u672A\u77E5\u9519\u8BEF"
389
397
  };
390
398
  var MGError = class extends Error {
@@ -498,6 +506,12 @@ var ConnectionManager = class {
498
506
  providers = /* @__PURE__ */ new Map();
499
507
  /** Consumer 连接 */
500
508
  consumers = /* @__PURE__ */ new Map();
509
+ /** Chrome 扩展连接(按扩展 ID 索引) */
510
+ chromeExtensions = /* @__PURE__ */ new Map();
511
+ /** 扩展序号映射(扩展 ID → 序号) */
512
+ extensionIndexMap = /* @__PURE__ */ new Map();
513
+ /** 下一个可用的扩展序号 */
514
+ nextExtensionIndex = 1;
501
515
  /** 所有连接(按 ID 索引) */
502
516
  allConnections = /* @__PURE__ */ new Map();
503
517
  /** 心跳检查定时器 */
@@ -592,6 +606,16 @@ var ConnectionManager = class {
592
606
  } else if (connectionInfo.type === "consumer" /* CONSUMER */) {
593
607
  this.consumers.delete(connectionId);
594
608
  this.logger.info(`Consumer \u65AD\u5F00: ${connectionId}`);
609
+ } else if (connectionInfo.type === "chrome_extension" /* CHROME_EXTENSION */) {
610
+ for (const [extensionId, extWs] of this.chromeExtensions) {
611
+ if (extWs.connectionId === connectionId) {
612
+ const index = this.extensionIndexMap.get(extensionId);
613
+ this.chromeExtensions.delete(extensionId);
614
+ this.extensionIndexMap.delete(extensionId);
615
+ this.logger.info(`Chrome \u6269\u5C55\u65AD\u5F00: ${extensionId} (\u5E8F\u53F7: #${index})`);
616
+ break;
617
+ }
618
+ }
595
619
  }
596
620
  }
597
621
  /**
@@ -645,6 +669,7 @@ var ConnectionManager = class {
645
669
  return {
646
670
  providers: providerCount,
647
671
  consumers: this.consumers.size,
672
+ extensions: this.chromeExtensions.size,
648
673
  total: this.allConnections.size
649
674
  };
650
675
  }
@@ -654,6 +679,48 @@ var ConnectionManager = class {
654
679
  getConnectedPageUrls() {
655
680
  return Array.from(this.providers.keys());
656
681
  }
682
+ /**
683
+ * 添加 Chrome 扩展连接
684
+ */
685
+ addChromeExtension(ws, extensionId) {
686
+ const managedWs = this.addConnection(ws, "chrome_extension" /* CHROME_EXTENSION */);
687
+ const index = this.nextExtensionIndex++;
688
+ this.extensionIndexMap.set(extensionId, index);
689
+ this.chromeExtensions.set(extensionId, managedWs);
690
+ this.logger.info(`Chrome \u6269\u5C55\u8FDE\u63A5: ${extensionId} (\u5206\u914D\u5E8F\u53F7: #${index})`);
691
+ return managedWs;
692
+ }
693
+ /**
694
+ * 根据序号查找扩展
695
+ */
696
+ findExtensionByIndex(index) {
697
+ for (const [extensionId, extIndex] of this.extensionIndexMap) {
698
+ if (extIndex === index) {
699
+ return this.chromeExtensions.get(extensionId);
700
+ }
701
+ }
702
+ return void 0;
703
+ }
704
+ /**
705
+ * 获取第一个扩展
706
+ */
707
+ getFirstExtension() {
708
+ return this.chromeExtensions.values().next().value;
709
+ }
710
+ /**
711
+ * 获取所有扩展信息
712
+ */
713
+ getAllExtensions() {
714
+ const result = [];
715
+ for (const [extensionId, ws] of this.chromeExtensions) {
716
+ const index = this.extensionIndexMap.get(extensionId);
717
+ if (index !== void 0) {
718
+ result.push({ index, extensionId, ws });
719
+ }
720
+ }
721
+ result.sort((a, b) => a.index - b.index);
722
+ return result;
723
+ }
657
724
  /**
658
725
  * 关闭所有连接
659
726
  */
@@ -665,6 +732,8 @@ var ConnectionManager = class {
665
732
  }
666
733
  this.providers.clear();
667
734
  this.consumers.clear();
735
+ this.chromeExtensions.clear();
736
+ this.extensionIndexMap.clear();
668
737
  this.allConnections.clear();
669
738
  }
670
739
  };
@@ -782,6 +851,24 @@ var RequestHandler = class {
782
851
  this.logger.error(`\u53D1\u9001\u9519\u8BEF\u54CD\u5E94\u5931\u8D25: ${requestId}`, err);
783
852
  }
784
853
  }
854
+ /**
855
+ * 注册待处理请求(供外部使用,如 OPEN_PAGE)
856
+ * @param requestId 请求 ID
857
+ * @param consumer 发起请求的 Consumer
858
+ * @param sendCallback 发送请求的回调函数
859
+ */
860
+ registerPendingRequest(requestId, consumer, sendCallback) {
861
+ const timer = setTimeout(() => {
862
+ this.handleTimeout(requestId);
863
+ }, REQUEST_TIMEOUT);
864
+ this.pendingRequests.set(requestId, {
865
+ id: requestId,
866
+ consumer,
867
+ timer,
868
+ timestamp: Date.now()
869
+ });
870
+ sendCallback();
871
+ }
785
872
  /**
786
873
  * 清理特定连接的所有待处理请求
787
874
  */
@@ -961,12 +1048,22 @@ var MGServer = class {
961
1048
  */
962
1049
  handleRegister(ws, message) {
963
1050
  const { connectionType, pageUrl, pageId } = message.data;
964
- const managedWs = this.connectionManager.addConnection(
965
- ws,
966
- connectionType,
967
- pageUrl,
968
- pageId
969
- );
1051
+ const extensionId = message.data.extensionId;
1052
+ let managedWs;
1053
+ let extensionIndex;
1054
+ if (connectionType === "chrome_extension" /* CHROME_EXTENSION */ && extensionId) {
1055
+ managedWs = this.connectionManager.addChromeExtension(ws, extensionId);
1056
+ const exts = this.connectionManager.getAllExtensions();
1057
+ const ext = exts.find((e) => e.extensionId === extensionId);
1058
+ extensionIndex = ext?.index;
1059
+ } else {
1060
+ managedWs = this.connectionManager.addConnection(
1061
+ ws,
1062
+ connectionType,
1063
+ pageUrl,
1064
+ pageId
1065
+ );
1066
+ }
970
1067
  const ack = {
971
1068
  id: message.id || "",
972
1069
  type: "register_ack" /* REGISTER_ACK */,
@@ -974,7 +1071,8 @@ var MGServer = class {
974
1071
  data: {
975
1072
  connectionId: managedWs.connectionId,
976
1073
  pageUrl,
977
- serverVersion: getVersion()
1074
+ serverVersion: getVersion(),
1075
+ ...extensionIndex !== void 0 && { extensionIndex }
978
1076
  }
979
1077
  };
980
1078
  ws.send(JSON.stringify(ack));
@@ -991,6 +1089,15 @@ var MGServer = class {
991
1089
  case "get_server_status" /* GET_SERVER_STATUS */:
992
1090
  this.handleGetServerStatus(ws, message);
993
1091
  break;
1092
+ case "list_extensions" /* LIST_EXTENSIONS */:
1093
+ this.handleListExtensions(ws, message);
1094
+ break;
1095
+ case "open_page" /* OPEN_PAGE */:
1096
+ this.handleOpenPage(ws, message);
1097
+ break;
1098
+ case "navigate_to_node" /* NAVIGATE_TO_NODE */:
1099
+ this.handleNavigateToNode(ws, message);
1100
+ break;
994
1101
  case "response" /* RESPONSE */:
995
1102
  case "error" /* ERROR */:
996
1103
  this.requestHandler.handleResponse(message);
@@ -1023,6 +1130,13 @@ var MGServer = class {
1023
1130
  connectedAt: info.connectedAt.toISOString(),
1024
1131
  lastActiveAt: info.lastActiveAt.toISOString()
1025
1132
  }));
1133
+ const extensions = this.connectionManager.getAllExtensions();
1134
+ const connectedExtensions = extensions.map((ext) => ({
1135
+ index: ext.index,
1136
+ extensionId: ext.extensionId,
1137
+ connectedAt: ext.ws.connectionInfo.connectedAt.toISOString(),
1138
+ lastActiveAt: ext.ws.connectionInfo.lastActiveAt.toISOString()
1139
+ }));
1026
1140
  const uptimeMs = this.startedAt ? Date.now() - this.startedAt.getTime() : 0;
1027
1141
  const statusData = {
1028
1142
  running: this.isRunning,
@@ -1032,7 +1146,8 @@ var MGServer = class {
1032
1146
  uptime: formatDuration(uptimeMs),
1033
1147
  version: getVersion(),
1034
1148
  stats,
1035
- connectedPages
1149
+ connectedPages,
1150
+ connectedExtensions
1036
1151
  };
1037
1152
  const response = {
1038
1153
  id: message.id || "",
@@ -1043,6 +1158,156 @@ var MGServer = class {
1043
1158
  ws.send(JSON.stringify(response));
1044
1159
  this.logger.info("\u8FD4\u56DE Server \u72B6\u6001\u4FE1\u606F");
1045
1160
  }
1161
+ /**
1162
+ * 处理扩展列表查询
1163
+ */
1164
+ handleListExtensions(ws, message) {
1165
+ const extensions = this.connectionManager.getAllExtensions();
1166
+ const extensionList = extensions.map((ext) => ({
1167
+ index: ext.index,
1168
+ extensionId: ext.extensionId,
1169
+ connectedAt: ext.ws.connectionInfo.connectedAt.toISOString(),
1170
+ lastActiveAt: ext.ws.connectionInfo.lastActiveAt.toISOString()
1171
+ }));
1172
+ const response = {
1173
+ id: message.id || "",
1174
+ type: "response" /* RESPONSE */,
1175
+ success: true,
1176
+ data: {
1177
+ extensions: extensionList,
1178
+ totalCount: extensionList.length
1179
+ }
1180
+ };
1181
+ ws.send(JSON.stringify(response));
1182
+ this.logger.info(`\u8FD4\u56DE\u6269\u5C55\u5217\u8868\uFF0C\u5171 ${extensionList.length} \u4E2A\u6269\u5C55`);
1183
+ }
1184
+ /**
1185
+ * 处理打开页面请求
1186
+ */
1187
+ handleOpenPage(ws, message) {
1188
+ const params = message.params;
1189
+ const requestId = message.id || "";
1190
+ if (!params?.url) {
1191
+ const errorResponse = {
1192
+ id: requestId,
1193
+ type: "error" /* ERROR */,
1194
+ success: false,
1195
+ error: {
1196
+ code: "E011" /* INVALID_PARAMS */,
1197
+ name: "INVALID_PARAMS",
1198
+ message: "\u7F3A\u5C11 url \u53C2\u6570"
1199
+ }
1200
+ };
1201
+ ws.send(JSON.stringify(errorResponse));
1202
+ return;
1203
+ }
1204
+ const targetIndex = params.extensionIndex || 1;
1205
+ const targetExtension = this.connectionManager.findExtensionByIndex(targetIndex);
1206
+ if (!targetExtension) {
1207
+ const errorResponse = {
1208
+ id: requestId,
1209
+ type: "error" /* ERROR */,
1210
+ success: false,
1211
+ error: {
1212
+ code: "E018" /* NO_EXTENSION_CONNECTED */,
1213
+ name: "NO_EXTENSION_CONNECTED",
1214
+ message: targetIndex === 1 ? "\u6CA1\u6709 Chrome \u6269\u5C55\u8FDE\u63A5\u5230 Server\u3002\u8BF7\u786E\u4FDD\u6D4F\u89C8\u5668\u5DF2\u6253\u5F00\u5E76\u5B89\u88C5\u4E86 MG Plugin" : `\u672A\u627E\u5230\u5E8F\u53F7\u4E3A #${targetIndex} \u7684\u6269\u5C55\u5B9E\u4F8B`
1215
+ }
1216
+ };
1217
+ ws.send(JSON.stringify(errorResponse));
1218
+ this.logger.warn(`\u672A\u627E\u5230\u6269\u5C55\u5B9E\u4F8B #${targetIndex}`);
1219
+ return;
1220
+ }
1221
+ const forwardMessage = {
1222
+ id: requestId,
1223
+ type: "open_page" /* OPEN_PAGE */,
1224
+ params: { url: params.url }
1225
+ };
1226
+ this.requestHandler.registerPendingRequest(requestId, ws, () => {
1227
+ try {
1228
+ targetExtension.send(JSON.stringify(forwardMessage));
1229
+ this.logger.info(`\u8F6C\u53D1 OPEN_PAGE \u8BF7\u6C42\u5230\u6269\u5C55 #${targetIndex}: ${params.url}`);
1230
+ } catch (error) {
1231
+ this.logger.error(`\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25: ${error}`);
1232
+ const errorResponse = {
1233
+ id: requestId,
1234
+ type: "error" /* ERROR */,
1235
+ success: false,
1236
+ error: {
1237
+ code: "E001" /* CONNECTION_FAILED */,
1238
+ name: "CONNECTION_FAILED",
1239
+ message: "\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25"
1240
+ }
1241
+ };
1242
+ ws.send(JSON.stringify(errorResponse));
1243
+ }
1244
+ });
1245
+ }
1246
+ /**
1247
+ * 处理节点导航请求
1248
+ */
1249
+ handleNavigateToNode(ws, message) {
1250
+ const params = message.params;
1251
+ const requestId = message.id || "";
1252
+ if (!params?.pageUrl || !params?.nodeId) {
1253
+ const errorResponse = {
1254
+ id: requestId,
1255
+ type: "error" /* ERROR */,
1256
+ success: false,
1257
+ error: {
1258
+ code: "E011" /* INVALID_PARAMS */,
1259
+ name: "INVALID_PARAMS",
1260
+ message: "\u7F3A\u5C11 pageUrl \u6216 nodeId \u53C2\u6570"
1261
+ }
1262
+ };
1263
+ ws.send(JSON.stringify(errorResponse));
1264
+ return;
1265
+ }
1266
+ const targetIndex = params.extensionIndex || 1;
1267
+ const targetExtension = this.connectionManager.findExtensionByIndex(targetIndex);
1268
+ if (!targetExtension) {
1269
+ const errorResponse = {
1270
+ id: requestId,
1271
+ type: "error" /* ERROR */,
1272
+ success: false,
1273
+ error: {
1274
+ code: "E018" /* NO_EXTENSION_CONNECTED */,
1275
+ name: "NO_EXTENSION_CONNECTED",
1276
+ message: targetIndex === 1 ? "\u6CA1\u6709 Chrome \u6269\u5C55\u8FDE\u63A5\u5230 Server\u3002\u8BF7\u786E\u4FDD\u6D4F\u89C8\u5668\u5DF2\u6253\u5F00\u5E76\u5B89\u88C5\u4E86 MG Plugin" : `\u672A\u627E\u5230\u5E8F\u53F7\u4E3A #${targetIndex} \u7684\u6269\u5C55\u5B9E\u4F8B`
1277
+ }
1278
+ };
1279
+ ws.send(JSON.stringify(errorResponse));
1280
+ this.logger.warn(`\u672A\u627E\u5230\u6269\u5C55\u5B9E\u4F8B #${targetIndex}`);
1281
+ return;
1282
+ }
1283
+ const forwardMessage = {
1284
+ id: requestId,
1285
+ type: "navigate_to_node" /* NAVIGATE_TO_NODE */,
1286
+ params: {
1287
+ pageUrl: params.pageUrl,
1288
+ nodeId: params.nodeId
1289
+ }
1290
+ };
1291
+ this.requestHandler.registerPendingRequest(requestId, ws, () => {
1292
+ try {
1293
+ targetExtension.send(JSON.stringify(forwardMessage));
1294
+ this.logger.info(`\u8F6C\u53D1 NAVIGATE_TO_NODE \u8BF7\u6C42\u5230\u6269\u5C55 #${targetIndex}: ${params.pageUrl} -> ${params.nodeId}`);
1295
+ } catch (error) {
1296
+ this.logger.error(`\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25: ${error}`);
1297
+ const errorResponse = {
1298
+ id: requestId,
1299
+ type: "error" /* ERROR */,
1300
+ success: false,
1301
+ error: {
1302
+ code: "E001" /* CONNECTION_FAILED */,
1303
+ name: "CONNECTION_FAILED",
1304
+ message: "\u8F6C\u53D1\u8BF7\u6C42\u5931\u8D25"
1305
+ }
1306
+ };
1307
+ ws.send(JSON.stringify(errorResponse));
1308
+ }
1309
+ });
1310
+ }
1046
1311
  /**
1047
1312
  * 停止服务器
1048
1313
  */
@@ -1529,7 +1794,7 @@ import { writeFileSync as writeFileSync2 } from "fs";
1529
1794
  import { resolve as resolve2, dirname as dirname5 } from "path";
1530
1795
  import { mkdirSync as mkdirSync3 } from "fs";
1531
1796
  function createGetNodeByIdCommand() {
1532
- return new Command2("get_node_by_id").description("\u6839\u636E\u8282\u70B9 ID \u83B7\u53D6\u8282\u70B9\u8BE6\u7EC6\u4FE1\u606F\u3002\u6570\u636E\u4FDD\u5B58\u5230\u6307\u5B9A JSON \u6587\u4EF6\uFF0C\u8FD4\u56DE\u6587\u4EF6\u8DEF\u5F84\u548C\u5927\u5C0F\u4FE1\u606F\u3002\u5982\u9700\u901A\u8FC7\u94FE\u63A5\u83B7\u53D6\uFF0C\u8BF7\u4F7F\u7528 get_node_by_link \u547D\u4EE4").requiredOption("--nodeId <id>", "\u8282\u70B9 ID\uFF0C\u683C\u5F0F\u5982 123:456\u3002\u53EF\u4ECE MasterGo \u6D6E\u7A97\u94FE\u63A5\u4E2D\u83B7\u53D6").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84\u3002\u652F\u6301\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u8DEF\u5F84").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com\u3002\u4E0E --fileId \u914D\u5408\u4F7F\u7528", "mastergo.netease.com").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\uFF0C\u4E0E --domain \u914D\u5408\u6307\u5B9A\u76EE\u6807\u9875\u9762").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6\uFF0C\u9ED8\u8BA4 1\u3002\u589E\u52A0\u6DF1\u5EA6\u4F1A\u663E\u8457\u589E\u52A0\u6570\u636E\u91CF", "1").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9\uFF08visible: false\uFF09\uFF0C\u9ED8\u8BA4\u4E0D\u5305\u542B", false).option("--raw", "\u4FDD\u7559\u539F\u59CB\u6570\u636E\uFF0C\u4E0D\u7CBE\u7B80\u9ED8\u8BA4\u503C\u5B57\u6BB5", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
1797
+ return new Command2("get_node_by_id").description("\u6839\u636E\u8282\u70B9 ID \u83B7\u53D6\u8282\u70B9\u8BE6\u7EC6\u4FE1\u606F\u3002\u6570\u636E\u4FDD\u5B58\u5230\u6307\u5B9A JSON \u6587\u4EF6\uFF0C\u8FD4\u56DE\u6587\u4EF6\u8DEF\u5F84\u548C\u5927\u5C0F\u4FE1\u606F\u3002\u5982\u9700\u901A\u8FC7\u94FE\u63A5\u83B7\u53D6\uFF0C\u8BF7\u4F7F\u7528 get_node_by_link \u547D\u4EE4").requiredOption("--nodeId <id>", "\u8282\u70B9 ID\uFF0C\u683C\u5F0F\u5982 123:456\u3002\u53EF\u4ECE MasterGo \u6D6E\u7A97\u94FE\u63A5\u4E2D\u83B7\u53D6").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84\u3002\u652F\u6301\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u8DEF\u5F84").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com\u3002\u4E0E --fileId \u914D\u5408\u4F7F\u7528", "mastergo.netease.com").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\uFF0C\u4E0E --domain \u914D\u5408\u6307\u5B9A\u76EE\u6807\u9875\u9762").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6\uFF0C\u9ED8\u8BA4 1\u3002\u589E\u52A0\u6DF1\u5EA6\u4F1A\u663E\u8457\u589E\u52A0\u6570\u636E\u91CF", "1").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9\uFF08visible: false\uFF09\uFF0C\u9ED8\u8BA4\u4E0D\u5305\u542B", false).option("--raw", "\u4FDD\u7559\u539F\u59CB\u6570\u636E\uFF0C\u4E0D\u7CBE\u7B80\u9ED8\u8BA4\u503C\u5B57\u6BB5", false).option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
1533
1798
  await handleGetNodeById(options);
1534
1799
  });
1535
1800
  }
@@ -1555,7 +1820,7 @@ async function handleGetNodeById(options) {
1555
1820
  const outputPath = resolve2(options.output);
1556
1821
  const outputDir = dirname5(outputPath);
1557
1822
  mkdirSync3(outputDir, { recursive: true });
1558
- const jsonContent = JSON.stringify(outputData, null, 2);
1823
+ const jsonContent = JSON.stringify(outputData, null, options.pretty ? 2 : 0);
1559
1824
  writeFileSync2(outputPath, jsonContent, "utf-8");
1560
1825
  const size = jsonContent.length;
1561
1826
  const sizeKB = (size / 1024).toFixed(2);
@@ -1563,6 +1828,7 @@ async function handleGetNodeById(options) {
1563
1828
  console.log(`\u8282\u70B9 ID: ${options.nodeId}`);
1564
1829
  console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
1565
1830
  console.log(`\u8282\u70B9\u6DF1\u5EA6: ${params.maxDepth}`);
1831
+ console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
1566
1832
  if (!options.raw) {
1567
1833
  console.log(`\u6570\u636E\u6A21\u5F0F: \u7CBE\u7B80\u6A21\u5F0F (\u4F7F\u7528 --raw \u83B7\u53D6\u5B8C\u6574\u6570\u636E)`);
1568
1834
  }
@@ -1580,7 +1846,7 @@ import { writeFileSync as writeFileSync3 } from "fs";
1580
1846
  import { resolve as resolve3, dirname as dirname6 } from "path";
1581
1847
  import { mkdirSync as mkdirSync4 } from "fs";
1582
1848
  function createGetNodeByLinkCommand() {
1583
- return new Command3("get_node_by_link").description("\u89E3\u6790 mgp:// \u534F\u8BAE\u94FE\u63A5\u5E76\u83B7\u53D6\u8282\u70B9/\u9875\u9762\u4FE1\u606F").requiredOption("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5\uFF08\u652F\u6301 nodeId \u548C pageId\uFF09").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6", "1").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9", false).option("--raw", "\u4FDD\u7559\u539F\u59CB\u6570\u636E\uFF0C\u4E0D\u7CBE\u7B80\u9ED8\u8BA4\u503C\u5B57\u6BB5", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
1849
+ return new Command3("get_node_by_link").description("\u89E3\u6790 mgp:// \u534F\u8BAE\u94FE\u63A5\u5E76\u83B7\u53D6\u8282\u70B9/\u9875\u9762\u4FE1\u606F").requiredOption("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5\uFF08\u652F\u6301 nodeId \u548C pageId\uFF09").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6", "1").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9", false).option("--raw", "\u4FDD\u7559\u539F\u59CB\u6570\u636E\uFF0C\u4E0D\u7CBE\u7B80\u9ED8\u8BA4\u503C\u5B57\u6BB5", false).option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
1584
1850
  await handleGetNodeByLink(options);
1585
1851
  });
1586
1852
  }
@@ -1630,7 +1896,7 @@ async function handleGetNodeByLink(options) {
1630
1896
  const outputPath = resolve3(options.output);
1631
1897
  const outputDir = dirname6(outputPath);
1632
1898
  mkdirSync4(outputDir, { recursive: true });
1633
- const jsonContent = JSON.stringify(outputData, null, 2);
1899
+ const jsonContent = JSON.stringify(outputData, null, options.pretty ? 2 : 0);
1634
1900
  writeFileSync3(outputPath, jsonContent, "utf-8");
1635
1901
  const size = jsonContent.length;
1636
1902
  const sizeKB = (size / 1024).toFixed(2);
@@ -1646,6 +1912,7 @@ async function handleGetNodeByLink(options) {
1646
1912
  }
1647
1913
  console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
1648
1914
  console.log(`\u904D\u5386\u6DF1\u5EA6: ${options.maxDepth || "1"}`);
1915
+ console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
1649
1916
  if (!options.raw) {
1650
1917
  console.log(`\u6570\u636E\u6A21\u5F0F: \u7CBE\u7B80\u6A21\u5F0F (\u4F7F\u7528 --raw \u83B7\u53D6\u5B8C\u6574\u6570\u636E)`);
1651
1918
  }
@@ -1667,7 +1934,7 @@ import { writeFileSync as writeFileSync4 } from "fs";
1667
1934
  import { resolve as resolve4, dirname as dirname7 } from "path";
1668
1935
  import { mkdirSync as mkdirSync5 } from "fs";
1669
1936
  function createGetAllNodesCommand() {
1670
- return new Command4("get_all_nodes").description("\u83B7\u53D6\u5F53\u524D\u9875\u9762\u7684\u6240\u6709\u8282\u70B9\u6811\u3002\u8B66\u544A\uFF1A\u6DF1\u5EA6\u6BCF\u589E\u52A0 1\uFF0C\u6570\u636E\u91CF\u53EF\u80FD\u5448\u6307\u6570\u7EA7\u589E\u957F\u3002\u5EFA\u8BAE\u4ECE maxDepth=1 \u5F00\u59CB").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84\u3002\u652F\u6301\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u8DEF\u5F84").option("--maxDepth <number>", "\u6700\u5927\u6DF1\u5EA6\uFF0C\u9ED8\u8BA4 1\u3002\u6DF1\u5EA6 2 \u53EF\u80FD\u4EA7\u751F 100KB-500KB\uFF0C\u6DF1\u5EA6 3 \u53EF\u80FD\u8D85\u8FC7 1MB", "1").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9\uFF08visible: false\uFF09\uFF0C\u9ED8\u8BA4\u4E0D\u5305\u542B", false).option("--raw", "\u4FDD\u7559\u539F\u59CB\u6570\u636E\uFF0C\u4E0D\u7CBE\u7B80\u9ED8\u8BA4\u503C\u5B57\u6BB5", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
1937
+ return new Command4("get_all_nodes").description("\u83B7\u53D6\u5F53\u524D\u9875\u9762\u7684\u6240\u6709\u8282\u70B9\u6811\u3002\u8B66\u544A\uFF1A\u6DF1\u5EA6\u6BCF\u589E\u52A0 1\uFF0C\u6570\u636E\u91CF\u53EF\u80FD\u5448\u6307\u6570\u7EA7\u589E\u957F\u3002\u5EFA\u8BAE\u4ECE maxDepth=1 \u5F00\u59CB").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84\u3002\u652F\u6301\u7EDD\u5BF9\u8DEF\u5F84\u6216\u76F8\u5BF9\u8DEF\u5F84").option("--maxDepth <number>", "\u6700\u5927\u6DF1\u5EA6\uFF0C\u9ED8\u8BA4 1\u3002\u6DF1\u5EA6 2 \u53EF\u80FD\u4EA7\u751F 100KB-500KB\uFF0C\u6DF1\u5EA6 3 \u53EF\u80FD\u8D85\u8FC7 1MB", "1").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9\uFF08visible: false\uFF09\uFF0C\u9ED8\u8BA4\u4E0D\u5305\u542B", false).option("--raw", "\u4FDD\u7559\u539F\u59CB\u6570\u636E\uFF0C\u4E0D\u7CBE\u7B80\u9ED8\u8BA4\u503C\u5B57\u6BB5", false).option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
1671
1938
  await handleGetAllNodes(options);
1672
1939
  });
1673
1940
  }
@@ -1687,7 +1954,7 @@ async function handleGetAllNodes(options) {
1687
1954
  const outputPath = resolve4(options.output);
1688
1955
  const outputDir = dirname7(outputPath);
1689
1956
  mkdirSync5(outputDir, { recursive: true });
1690
- const jsonContent = JSON.stringify(outputData, null, 2);
1957
+ const jsonContent = JSON.stringify(outputData, null, options.pretty ? 2 : 0);
1691
1958
  writeFileSync4(outputPath, jsonContent, "utf-8");
1692
1959
  const size = jsonContent.length;
1693
1960
  const sizeKB = (size / 1024).toFixed(2);
@@ -1696,6 +1963,7 @@ async function handleGetAllNodes(options) {
1696
1963
  console.log(`\u8282\u70B9\u6570\u91CF: ${nodeCount}`);
1697
1964
  console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
1698
1965
  console.log(`\u8282\u70B9\u6DF1\u5EA6: ${params.maxDepth}`);
1966
+ console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
1699
1967
  if (!options.raw) {
1700
1968
  console.log(`\u6570\u636E\u6A21\u5F0F: \u7CBE\u7B80\u6A21\u5F0F (\u4F7F\u7528 --raw \u83B7\u53D6\u5B8C\u6574\u6570\u636E)`);
1701
1969
  }
@@ -1895,7 +2163,7 @@ async function convertSvgToVector(svgPath, outputDir) {
1895
2163
  // src/cli/commands/execute-code.ts
1896
2164
  import { Command as Command6 } from "commander";
1897
2165
  function createExecuteCodeCommand() {
1898
- return new Command6("execute_code").description("\u5728 MasterGo \u9875\u9762\u6267\u884C\u81EA\u5B9A\u4E49 JavaScript \u4EE3\u7801\u3002\u901A\u8FC7 mg \u53D8\u91CF\u8BBF\u95EE MasterGo API\uFF0C\u7ED3\u679C\u4F1A\u88AB JSON \u5E8F\u5217\u5316\u8FD4\u56DE").argument("<code>", "\u8981\u6267\u884C\u7684\u4EE3\u7801\u3002\u53EF\u4F7F\u7528 mg \u53D8\u91CF\uFF0C\u5982 mg.currentPage.name\u3001mg.currentPage.selection").option("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5\uFF0C\u7528\u4E8E\u6307\u5B9A\u76EE\u6807\u9875\u9762\u3002\u4E0E --domain/--fileId \u4E8C\u9009\u4E00").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com", "mastergo.netease.com").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\uFF0C\u4E0E --domain \u914D\u5408\u6307\u5B9A\u76EE\u6807\u9875\u9762").option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (code, options) => {
2166
+ return new Command6("execute_code").description("\u5728 MasterGo \u9875\u9762\u6267\u884C\u81EA\u5B9A\u4E49 JavaScript \u4EE3\u7801\u3002\u901A\u8FC7 mg \u53D8\u91CF\u8BBF\u95EE MasterGo API\uFF0C\u7ED3\u679C\u4F1A\u88AB JSON \u5E8F\u5217\u5316\u8FD4\u56DE").argument("<code>", "\u8981\u6267\u884C\u7684\u4EE3\u7801\u3002\u53EF\u4F7F\u7528 mg \u53D8\u91CF\uFF0C\u5982 mg.currentPage.name\u3001mg.currentPage.selection").option("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5\uFF0C\u7528\u4E8E\u6307\u5B9A\u76EE\u6807\u9875\u9762\u3002\u4E0E --domain/--fileId \u4E8C\u9009\u4E00").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com", "mastergo.netease.com").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\uFF0C\u4E0E --domain \u914D\u5408\u6307\u5B9A\u76EE\u6807\u9875\u9762").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (code, options) => {
1899
2167
  await handleExecuteCode(code, options);
1900
2168
  });
1901
2169
  }
@@ -1928,7 +2196,7 @@ async function handleExecuteCode(code, options) {
1928
2196
  if (result === null || result === void 0) {
1929
2197
  console.log("\u6267\u884C\u5B8C\u6210\uFF08\u65E0\u8FD4\u56DE\u503C\uFF09");
1930
2198
  } else if (typeof result === "object") {
1931
- console.log(JSON.stringify(result, null, 2));
2199
+ console.log(JSON.stringify(result, null, options.pretty ? 2 : 0));
1932
2200
  } else {
1933
2201
  console.log(result);
1934
2202
  }
@@ -1947,7 +2215,7 @@ import { resolve as resolve6, dirname as dirname9 } from "path";
1947
2215
  import { mkdirSync as mkdirSync7 } from "fs";
1948
2216
  import { tmpdir as tmpdir2 } from "os";
1949
2217
  function createGetAllPagesCommand() {
1950
- return new Command7("get_all_pages").description("\u83B7\u53D6 MasterGo \u6587\u6863\u7684\u6240\u6709\u9875\u9762\u4FE1\u606F\u3002\u4E0D\u6307\u5B9A --output \u65F6\u4FDD\u5B58\u5230\u7CFB\u7EDF\u4E34\u65F6\u76EE\u5F55").option("--link <url>", "\u9875\u9762\u94FE\u63A5\u3002\u652F\u6301\u5B8C\u6574 URL \u6216 mgp:// \u534F\u8BAE").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\u3002\u4ECE URL \u4E2D /file/ \u540E\u9762\u7684\u6570\u5B57").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com\u3002\u4E0E --fileId \u914D\u5408\u4F7F\u7528", "mastergo.netease.com").option("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84\u3002\u4E0D\u6307\u5B9A\u5219\u4FDD\u5B58\u5230\u7CFB\u7EDF\u4E34\u65F6\u76EE\u5F55").option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
2218
+ return new Command7("get_all_pages").description("\u83B7\u53D6 MasterGo \u6587\u6863\u7684\u6240\u6709\u9875\u9762\u4FE1\u606F\u3002\u4E0D\u6307\u5B9A --output \u65F6\u4FDD\u5B58\u5230\u7CFB\u7EDF\u4E34\u65F6\u76EE\u5F55").option("--link <url>", "\u9875\u9762\u94FE\u63A5\u3002\u652F\u6301\u5B8C\u6574 URL \u6216 mgp:// \u534F\u8BAE").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\u3002\u4ECE URL \u4E2D /file/ \u540E\u9762\u7684\u6570\u5B57").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com\u3002\u4E0E --fileId \u914D\u5408\u4F7F\u7528", "mastergo.netease.com").option("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84\u3002\u4E0D\u6307\u5B9A\u5219\u4FDD\u5B58\u5230\u7CFB\u7EDF\u4E34\u65F6\u76EE\u5F55").option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
1951
2219
  await handleGetAllPages(options);
1952
2220
  });
1953
2221
  }
@@ -1993,7 +2261,7 @@ async function handleGetAllPages(options) {
1993
2261
  }
1994
2262
  const outputDir = dirname9(outputPath);
1995
2263
  mkdirSync7(outputDir, { recursive: true });
1996
- const jsonContent = JSON.stringify(data, null, 2);
2264
+ const jsonContent = JSON.stringify(data, null, options.pretty ? 2 : 0);
1997
2265
  writeFileSync6(outputPath, jsonContent, "utf-8");
1998
2266
  const size = jsonContent.length;
1999
2267
  const sizeKB = (size / 1024).toFixed(2);
@@ -2001,6 +2269,7 @@ async function handleGetAllPages(options) {
2001
2269
  console.log(`\u6587\u6863\u540D\u79F0: ${data.documentName}`);
2002
2270
  console.log(`\u9875\u9762\u6570\u91CF: ${data.totalCount}`);
2003
2271
  console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
2272
+ console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
2004
2273
  } catch (error) {
2005
2274
  console.error(`\u9519\u8BEF: ${error instanceof Error ? error.message : error}`);
2006
2275
  process.exit(1);
@@ -2015,7 +2284,7 @@ import { writeFileSync as writeFileSync7 } from "fs";
2015
2284
  import { resolve as resolve7, dirname as dirname10 } from "path";
2016
2285
  import { mkdirSync as mkdirSync8 } from "fs";
2017
2286
  function createGetNodeForSpaceCommand() {
2018
- return new Command8("get_node_for_space").description("\u83B7\u53D6\u8282\u70B9\u6216\u9875\u9762\u7684\u7A7A\u95F4\u4F4D\u7F6E\u4FE1\u606F\uFF08id\u3001name\u3001x\u3001y\u3001width\u3001height\uFF09\uFF0C\u7528\u4E8E AI \u7406\u89E3\u5143\u7D20\u5E03\u5C40\u3002\u9ED8\u8BA4\u83B7\u53D6\u6700\u6DF1\u5C42\u7EA7\u3002\u652F\u6301 nodeId \u548C pageId \u94FE\u63A5").option("--nodeId <id>", "\u8282\u70B9 ID\uFF0C\u683C\u5F0F\u5982 123:456\u3002\u4E0E --link \u4E8C\u9009\u4E00").option("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5\uFF08\u652F\u6301 nodeId \u548C pageId\uFF09\u3002\u4E0E --nodeId \u4E8C\u9009\u4E00").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com\u3002\u4E0E --nodeId \u914D\u5408\u4F7F\u7528", "mastergo.netease.com").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\uFF0C\u4E0E --domain \u548C --nodeId \u914D\u5408\u4F7F\u7528").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6\uFF0C\u9ED8\u8BA4 99\uFF08\u83B7\u53D6\u6700\u6DF1\u5C42\u7EA7\uFF09", "99").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
2287
+ return new Command8("get_node_for_space").description("\u83B7\u53D6\u8282\u70B9\u6216\u9875\u9762\u7684\u7A7A\u95F4\u4F4D\u7F6E\u4FE1\u606F\uFF08id\u3001name\u3001x\u3001y\u3001width\u3001height\uFF09\uFF0C\u7528\u4E8E AI \u7406\u89E3\u5143\u7D20\u5E03\u5C40\u3002\u9ED8\u8BA4\u83B7\u53D6\u6700\u6DF1\u5C42\u7EA7\u3002\u652F\u6301 nodeId \u548C pageId \u94FE\u63A5").option("--nodeId <id>", "\u8282\u70B9 ID\uFF0C\u683C\u5F0F\u5982 123:456\u3002\u4E0E --link \u4E8C\u9009\u4E00").option("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5\uFF08\u652F\u6301 nodeId \u548C pageId\uFF09\u3002\u4E0E --nodeId \u4E8C\u9009\u4E00").requiredOption("--output <path>", "\u8F93\u51FA JSON \u6587\u4EF6\u8DEF\u5F84").option("--domain <domain>", "MasterGo \u57DF\u540D\uFF0C\u9ED8\u8BA4 mastergo.netease.com\u3002\u4E0E --nodeId \u914D\u5408\u4F7F\u7528", "mastergo.netease.com").option("--fileId <id>", "\u6587\u4EF6 ID\uFF08\u7EAF\u6570\u5B57\uFF09\uFF0C\u4E0E --domain \u548C --nodeId \u914D\u5408\u4F7F\u7528").option("--maxDepth <number>", "\u904D\u5386\u6DF1\u5EA6\uFF0C\u9ED8\u8BA4 99\uFF08\u83B7\u53D6\u6700\u6DF1\u5C42\u7EA7\uFF09", "99").option("--includeInvisible", "\u5305\u542B\u4E0D\u53EF\u89C1\u8282\u70B9", false).option("--pretty", "\u683C\u5F0F\u5316\u8F93\u51FA JSON\uFF08\u9ED8\u8BA4\u538B\u7F29\uFF09", false).option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
2019
2288
  await handleGetNodeForSpace(options);
2020
2289
  });
2021
2290
  }
@@ -2094,7 +2363,7 @@ async function handleGetNodeForSpace(options) {
2094
2363
  const outputPath = resolve7(options.output);
2095
2364
  const outputDir = dirname10(outputPath);
2096
2365
  mkdirSync8(outputDir, { recursive: true });
2097
- const jsonContent = JSON.stringify(spaceData, null, 2);
2366
+ const jsonContent = JSON.stringify(spaceData, null, options.pretty ? 2 : 0);
2098
2367
  writeFileSync7(outputPath, jsonContent, "utf-8");
2099
2368
  const size = jsonContent.length;
2100
2369
  const sizeKB = (size / 1024).toFixed(2);
@@ -2112,6 +2381,7 @@ async function handleGetNodeForSpace(options) {
2112
2381
  }
2113
2382
  console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
2114
2383
  console.log(`\u8282\u70B9\u6DF1\u5EA6: ${maxDepth}`);
2384
+ console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
2115
2385
  console.log(`\u6570\u636E\u6A21\u5F0F: \u7A7A\u95F4\u4FE1\u606F (\u4EC5 id, name, x, y, width, height)`);
2116
2386
  } catch (error) {
2117
2387
  if (error instanceof MGError) {
@@ -2125,8 +2395,229 @@ async function handleGetNodeForSpace(options) {
2125
2395
  }
2126
2396
  }
2127
2397
 
2398
+ // src/cli/commands/list-extensions.ts
2399
+ import { Command as Command9 } from "commander";
2400
+ function createListExtensionsCommand() {
2401
+ return new Command9("list_extensions").description("\u5217\u51FA\u6240\u6709\u5DF2\u8FDE\u63A5\u7684 Chrome \u6269\u5C55\u5B9E\u4F8B").option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
2402
+ await handleListExtensions(options);
2403
+ });
2404
+ }
2405
+ async function handleListExtensions(options) {
2406
+ const client = new MGClient({
2407
+ noAutoStart: options.noAutoStart,
2408
+ noRetry: options.noRetry
2409
+ });
2410
+ try {
2411
+ await client.connect();
2412
+ const data = await client.requestWithRetry("list_extensions" /* LIST_EXTENSIONS */, {});
2413
+ if (data.totalCount === 0) {
2414
+ console.log("\u5F53\u524D\u6CA1\u6709\u8FDE\u63A5\u7684\u6269\u5C55\u5B9E\u4F8B");
2415
+ console.log("\n\u8BF7\u786E\u4FDD:");
2416
+ console.log(" 1. \u6D4F\u89C8\u5668\u5DF2\u6253\u5F00");
2417
+ console.log(" 2. \u5DF2\u5B89\u88C5 MG Plugin \u6269\u5C55");
2418
+ console.log(" 3. \u6269\u5C55\u5DF2\u6210\u529F\u8FDE\u63A5\u5230 Server");
2419
+ } else {
2420
+ console.log(`\u627E\u5230 ${data.totalCount} \u4E2A\u6269\u5C55\u5B9E\u4F8B:
2421
+ `);
2422
+ for (const ext of data.extensions) {
2423
+ const connectedAt = new Date(ext.connectedAt);
2424
+ const lastActiveAt = new Date(ext.lastActiveAt);
2425
+ console.log(`\u6269\u5C55 #${ext.index}`);
2426
+ console.log(` Extension ID: ${ext.extensionId}`);
2427
+ console.log(` \u8FDE\u63A5\u65F6\u95F4: ${connectedAt.toLocaleString()}`);
2428
+ console.log(` \u6700\u540E\u6D3B\u8DC3: ${lastActiveAt.toLocaleString()}`);
2429
+ console.log("");
2430
+ }
2431
+ }
2432
+ } catch (error) {
2433
+ console.error(`\u9519\u8BEF: ${error instanceof Error ? error.message : error}`);
2434
+ process.exit(1);
2435
+ } finally {
2436
+ client.close();
2437
+ }
2438
+ }
2439
+
2440
+ // src/cli/commands/open-page.ts
2441
+ import { Command as Command10 } from "commander";
2442
+ function createOpenPageCommand() {
2443
+ return new Command10("open_page").description("\u901A\u8FC7 Chrome \u6269\u5C55\u6253\u5F00\u6307\u5B9A\u7684\u9875\u9762").requiredOption("--url <url>", "\u8981\u6253\u5F00\u7684\u9875\u9762 URL\uFF08\u5B8C\u6574 HTTPS URL\uFF09").option("--ext <index>", "\u6269\u5C55\u5B9E\u4F8B\u5E8F\u53F7\uFF081, 2, 3...\uFF09\uFF0C\u9ED8\u8BA4\u81EA\u52A8\u9009\u62E9\u7B2C\u4E00\u4E2A\u53EF\u7528\u6269\u5C55").option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
2444
+ await handleOpenPage(options);
2445
+ });
2446
+ }
2447
+ async function handleOpenPage(options) {
2448
+ const client = new MGClient({
2449
+ noAutoStart: options.noAutoStart,
2450
+ noRetry: options.noRetry
2451
+ });
2452
+ try {
2453
+ if (!options.url.startsWith("https://") && !options.url.startsWith("http://")) {
2454
+ console.error("\u9519\u8BEF: URL \u5FC5\u987B\u4EE5 https:// \u6216 http:// \u5F00\u5934");
2455
+ console.error(`\u63D0\u4F9B\u7684 URL: ${options.url}`);
2456
+ process.exit(1);
2457
+ }
2458
+ await client.connect();
2459
+ let extensionIndex;
2460
+ if (typeof options.ext === "string") {
2461
+ extensionIndex = parseInt(options.ext, 10);
2462
+ } else if (typeof options.ext === "number") {
2463
+ extensionIndex = options.ext;
2464
+ } else {
2465
+ const extensionsData = await client.requestWithRetry("list_extensions" /* LIST_EXTENSIONS */, {});
2466
+ if (extensionsData.totalCount === 0) {
2467
+ console.error("\u9519\u8BEF: \u6CA1\u6709 Chrome \u6269\u5C55\u8FDE\u63A5\u5230 Server\u3002\u8BF7\u786E\u4FDD\u6D4F\u89C8\u5668\u5DF2\u6253\u5F00\u5E76\u5B89\u88C5\u4E86 MG Plugin");
2468
+ console.error("\n\u{1F4A1} \u89E3\u51B3\u65B9\u6CD5:");
2469
+ console.error(" 1. \u67E5\u770B\u53EF\u7528\u7684\u6269\u5C55\u5B9E\u4F8B:");
2470
+ console.error(" npx -y @hangox/mg-cli@latest list_extensions");
2471
+ console.error("");
2472
+ console.error(" 2. \u5982\u679C\u6CA1\u6709\u6269\u5C55\u8FDE\u63A5\uFF0C\u8BF7\u68C0\u67E5:");
2473
+ console.error(" \u2022 \u6D4F\u89C8\u5668\u662F\u5426\u5DF2\u6253\u5F00");
2474
+ console.error(" \u2022 MG Plugin \u6269\u5C55\u662F\u5426\u5DF2\u5B89\u88C5\u5E76\u542F\u7528");
2475
+ console.error(" \u2022 \u5C1D\u8BD5\u5237\u65B0\u6D4F\u89C8\u5668\u9875\u9762\u6216\u91CD\u65B0\u52A0\u8F7D\u6269\u5C55");
2476
+ process.exit(1);
2477
+ }
2478
+ extensionIndex = extensionsData.extensions[0].index;
2479
+ console.log(`\u672A\u6307\u5B9A\u6269\u5C55\u5E8F\u53F7\uFF0C\u81EA\u52A8\u4F7F\u7528\u6269\u5C55 #${extensionIndex}`);
2480
+ }
2481
+ if (isNaN(extensionIndex) || extensionIndex < 1) {
2482
+ console.error("\u9519\u8BEF: \u6269\u5C55\u5E8F\u53F7\u5FC5\u987B\u662F\u5927\u4E8E 0 \u7684\u6574\u6570");
2483
+ console.error(`\u63D0\u4F9B\u7684\u5E8F\u53F7: ${options.ext}`);
2484
+ process.exit(1);
2485
+ }
2486
+ console.log(`\u6B63\u5728\u901A\u8FC7\u6269\u5C55 #${extensionIndex} \u6253\u5F00\u9875\u9762...`);
2487
+ console.log(`URL: ${options.url}`);
2488
+ const params = {
2489
+ url: options.url,
2490
+ extensionIndex
2491
+ };
2492
+ const data = await client.requestWithRetry(
2493
+ "open_page" /* OPEN_PAGE */,
2494
+ params
2495
+ );
2496
+ console.log(`
2497
+ \u2713 \u9875\u9762\u5DF2\u6253\u5F00`);
2498
+ console.log(`Tab ID: ${data.tabId}`);
2499
+ } catch (error) {
2500
+ console.error(`
2501
+ \u9519\u8BEF: ${error instanceof Error ? error.message : error}`);
2502
+ const errorMsg = error instanceof Error ? error.message : String(error);
2503
+ if (errorMsg.includes("NO_EXTENSION_CONNECTED") || errorMsg.includes("\u672A\u627E\u5230")) {
2504
+ console.error("\n\u{1F4A1} \u89E3\u51B3\u65B9\u6CD5:");
2505
+ console.error(" 1. \u67E5\u770B\u53EF\u7528\u7684\u6269\u5C55\u5B9E\u4F8B:");
2506
+ console.error(" npx -y @hangox/mg-cli@latest list_extensions");
2507
+ console.error("");
2508
+ console.error(" 2. \u5982\u679C\u6CA1\u6709\u6269\u5C55\u8FDE\u63A5\uFF0C\u8BF7\u68C0\u67E5:");
2509
+ console.error(" \u2022 \u6D4F\u89C8\u5668\u662F\u5426\u5DF2\u6253\u5F00");
2510
+ console.error(" \u2022 MG Plugin \u6269\u5C55\u662F\u5426\u5DF2\u5B89\u88C5\u5E76\u542F\u7528");
2511
+ console.error(" \u2022 \u5C1D\u8BD5\u5237\u65B0\u6D4F\u89C8\u5668\u9875\u9762\u6216\u91CD\u65B0\u52A0\u8F7D\u6269\u5C55");
2512
+ console.error("");
2513
+ console.error(" 3. \u67E5\u770B\u6269\u5C55\u5B89\u88C5\u6307\u5357:");
2514
+ console.error(" https://github.com/hangox/MasterGoPlugin#chrome-plugin");
2515
+ }
2516
+ process.exit(1);
2517
+ } finally {
2518
+ client.close();
2519
+ }
2520
+ }
2521
+
2522
+ // src/cli/commands/navigate-to-node.ts
2523
+ import { Command as Command11 } from "commander";
2524
+ function createNavigateToNodeCommand() {
2525
+ return new Command11("navigate_to_node").description("\u5BFC\u822A\u5230 mgp:// \u94FE\u63A5\u6307\u5B9A\u7684\u8282\u70B9\uFF08\u81EA\u52A8\u5207\u6362\u6216\u6253\u5F00\u9875\u9762\uFF09").requiredOption("--link <url>", "mgp:// \u534F\u8BAE\u94FE\u63A5").option("--ext <index>", "\u6269\u5C55\u5B9E\u4F8B\u5E8F\u53F7\uFF081, 2, 3...\uFF09\uFF0C\u9ED8\u8BA4\u81EA\u52A8\u9009\u62E9\u7B2C\u4E00\u4E2A\u53EF\u7528\u6269\u5C55").option("--no-auto-start", "\u7981\u7528\u81EA\u52A8\u542F\u52A8 Server").option("--no-retry", "\u7981\u7528\u81EA\u52A8\u91CD\u8BD5").action(async (options) => {
2526
+ await handleNavigateToNode(options);
2527
+ });
2528
+ }
2529
+ async function handleNavigateToNode(options) {
2530
+ const parsed = parseMgpLink(options.link);
2531
+ if (!parsed) {
2532
+ console.error(`\u9519\u8BEF [${"E010" /* INVALID_LINK */}]: \u65E0\u6548\u7684 mgp:// \u94FE\u63A5\u683C\u5F0F`);
2533
+ console.error(`\u63D0\u4F9B\u7684\u94FE\u63A5: ${options.link}`);
2534
+ console.error(`\u671F\u671B\u683C\u5F0F: mgp://[mastergo_page_url]?nodeId=[\u8282\u70B9ID]`);
2535
+ process.exit(1);
2536
+ }
2537
+ const { pageUrl, nodeId } = parsed;
2538
+ if (!nodeId) {
2539
+ console.error(`\u9519\u8BEF [${"E010" /* INVALID_LINK */}]: \u94FE\u63A5\u5FC5\u987B\u5305\u542B nodeId \u53C2\u6570`);
2540
+ console.error(`\u63D0\u4F9B\u7684\u94FE\u63A5: ${options.link}`);
2541
+ console.error(`\u671F\u671B\u683C\u5F0F: mgp://[mastergo_page_url]?nodeId=[\u8282\u70B9ID]`);
2542
+ process.exit(1);
2543
+ }
2544
+ const client = new MGClient({
2545
+ noAutoStart: options.noAutoStart,
2546
+ noRetry: options.noRetry
2547
+ });
2548
+ try {
2549
+ await client.connect();
2550
+ let extensionIndex;
2551
+ if (typeof options.ext === "string") {
2552
+ extensionIndex = parseInt(options.ext, 10);
2553
+ } else if (typeof options.ext === "number") {
2554
+ extensionIndex = options.ext;
2555
+ } else {
2556
+ const extensionsData = await client.requestWithRetry("list_extensions" /* LIST_EXTENSIONS */, {});
2557
+ if (extensionsData.totalCount === 0) {
2558
+ console.error("\u9519\u8BEF: \u6CA1\u6709 Chrome \u6269\u5C55\u8FDE\u63A5\u5230 Server\u3002\u8BF7\u786E\u4FDD\u6D4F\u89C8\u5668\u5DF2\u6253\u5F00\u5E76\u5B89\u88C5\u4E86 MG Plugin");
2559
+ console.error("\n\u{1F4A1} \u89E3\u51B3\u65B9\u6CD5:");
2560
+ console.error(" 1. \u67E5\u770B\u53EF\u7528\u7684\u6269\u5C55\u5B9E\u4F8B:");
2561
+ console.error(" npx -y @hangox/mg-cli@latest list_extensions");
2562
+ console.error("");
2563
+ console.error(" 2. \u5982\u679C\u6CA1\u6709\u6269\u5C55\u8FDE\u63A5\uFF0C\u8BF7\u68C0\u67E5:");
2564
+ console.error(" \u2022 \u6D4F\u89C8\u5668\u662F\u5426\u5DF2\u6253\u5F00");
2565
+ console.error(" \u2022 MG Plugin \u6269\u5C55\u662F\u5426\u5DF2\u5B89\u88C5\u5E76\u542F\u7528");
2566
+ console.error(" \u2022 \u5C1D\u8BD5\u5237\u65B0\u6D4F\u89C8\u5668\u9875\u9762\u6216\u91CD\u65B0\u52A0\u8F7D\u6269\u5C55");
2567
+ process.exit(1);
2568
+ }
2569
+ extensionIndex = extensionsData.extensions[0].index;
2570
+ console.log(`\u672A\u6307\u5B9A\u6269\u5C55\u5E8F\u53F7\uFF0C\u81EA\u52A8\u4F7F\u7528\u6269\u5C55 #${extensionIndex}`);
2571
+ }
2572
+ if (isNaN(extensionIndex) || extensionIndex < 1) {
2573
+ console.error("\u9519\u8BEF: \u6269\u5C55\u5E8F\u53F7\u5FC5\u987B\u662F\u5927\u4E8E 0 \u7684\u6574\u6570");
2574
+ console.error(`\u63D0\u4F9B\u7684\u5E8F\u53F7: ${options.ext}`);
2575
+ process.exit(1);
2576
+ }
2577
+ console.log(`\u6B63\u5728\u901A\u8FC7\u6269\u5C55 #${extensionIndex} \u5BFC\u822A\u5230\u8282\u70B9...`);
2578
+ console.log(`\u9875\u9762 URL: ${pageUrl}`);
2579
+ console.log(`\u8282\u70B9 ID: ${nodeId}`);
2580
+ const params = {
2581
+ pageUrl,
2582
+ nodeId,
2583
+ extensionIndex
2584
+ };
2585
+ const data = await client.requestWithRetry("navigate_to_node" /* NAVIGATE_TO_NODE */, params);
2586
+ console.log(`
2587
+ \u2713 \u5BFC\u822A\u6210\u529F`);
2588
+ console.log(`\u64CD\u4F5C: ${data.action === "switched" ? "\u5207\u6362\u5230\u5DF2\u6253\u5F00\u7684 Tab" : "\u6253\u5F00\u65B0 Tab"}`);
2589
+ console.log(`Tab ID: ${data.tabId}`);
2590
+ console.log(`URL: ${data.url}`);
2591
+ } catch (error) {
2592
+ if (error instanceof MGError) {
2593
+ console.error(`
2594
+ \u9519\u8BEF [${error.code}]: ${error.message}`);
2595
+ } else {
2596
+ console.error(`
2597
+ \u9519\u8BEF: ${error instanceof Error ? error.message : error}`);
2598
+ }
2599
+ const errorMsg = error instanceof Error ? error.message : String(error);
2600
+ if (errorMsg.includes("NO_EXTENSION_CONNECTED") || errorMsg.includes("\u672A\u627E\u5230")) {
2601
+ console.error("\n\u{1F4A1} \u89E3\u51B3\u65B9\u6CD5:");
2602
+ console.error(" 1. \u67E5\u770B\u53EF\u7528\u7684\u6269\u5C55\u5B9E\u4F8B:");
2603
+ console.error(" npx -y @hangox/mg-cli@latest list_extensions");
2604
+ console.error("");
2605
+ console.error(" 2. \u5982\u679C\u6CA1\u6709\u6269\u5C55\u8FDE\u63A5\uFF0C\u8BF7\u68C0\u67E5:");
2606
+ console.error(" \u2022 \u6D4F\u89C8\u5668\u662F\u5426\u5DF2\u6253\u5F00");
2607
+ console.error(" \u2022 MG Plugin \u6269\u5C55\u662F\u5426\u5DF2\u5B89\u88C5\u5E76\u542F\u7528");
2608
+ console.error(" \u2022 \u5C1D\u8BD5\u5237\u65B0\u6D4F\u89C8\u5668\u9875\u9762\u6216\u91CD\u65B0\u52A0\u8F7D\u6269\u5C55");
2609
+ console.error("");
2610
+ console.error(" 3. \u67E5\u770B\u6269\u5C55\u5B89\u88C5\u6307\u5357:");
2611
+ console.error(" https://github.com/hangox/MasterGoPlugin#chrome-plugin");
2612
+ }
2613
+ process.exit(1);
2614
+ } finally {
2615
+ client.close();
2616
+ }
2617
+ }
2618
+
2128
2619
  // src/cli/index.ts
2129
- var program = new Command9();
2620
+ var program = new Command12();
2130
2621
  program.name("mg-cli").description("MasterGo CLI \u5DE5\u5177 - \u7528\u4E8E Claude Code \u4E0E MasterGo \u901A\u4FE1").version("1.0.0");
2131
2622
  program.addCommand(createServerCommand());
2132
2623
  program.addCommand(createGetNodeByIdCommand());
@@ -2136,5 +2627,8 @@ program.addCommand(createExportImageCommand());
2136
2627
  program.addCommand(createExecuteCodeCommand());
2137
2628
  program.addCommand(createGetAllPagesCommand());
2138
2629
  program.addCommand(createGetNodeForSpaceCommand());
2630
+ program.addCommand(createListExtensionsCommand());
2631
+ program.addCommand(createOpenPageCommand());
2632
+ program.addCommand(createNavigateToNodeCommand());
2139
2633
  program.parse();
2140
2634
  //# sourceMappingURL=cli.js.map