@hangox/mg-cli 1.0.7 → 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
  */
@@ -1232,19 +1497,8 @@ var MGClient = class {
1232
1497
  if (isProcessRunning(serverInfo.pid)) {
1233
1498
  const currentVersion = getVersion();
1234
1499
  if (!isVersionMatch(currentVersion, serverInfo.version)) {
1235
- console.log(`\u7248\u672C\u4E0D\u5339\u914D: CLI ${currentVersion} vs Server ${serverInfo.version}`);
1236
- console.log("\u6B63\u5728\u91CD\u542F Server \u4EE5\u5BF9\u9F50\u7248\u672C...");
1237
- try {
1238
- const newInfo = await restartServer(serverInfo.port);
1239
- console.log(`Server \u5DF2\u91CD\u542F\uFF0C\u7248\u672C: ${newInfo.version}`);
1240
- await this.waitForServer(newInfo.port);
1241
- return;
1242
- } catch (error) {
1243
- throw new MGError(
1244
- "E015" /* SERVER_START_FAILED */,
1245
- `\u91CD\u542F Server \u5931\u8D25: ${error instanceof Error ? error.message : error}`
1246
- );
1247
- }
1500
+ console.warn(`\u26A0\uFE0F \u7248\u672C\u4E0D\u5339\u914D: CLI ${currentVersion} vs Server ${serverInfo.version}`);
1501
+ console.warn("\u63D0\u793A: \u5982\u9700\u5BF9\u9F50\u7248\u672C\uFF0C\u8BF7\u624B\u52A8\u8FD0\u884C `npx -y @hangox/mg-cli@latest server restart`");
1248
1502
  }
1249
1503
  try {
1250
1504
  await this.tryConnect(serverInfo.port);
@@ -1540,7 +1794,7 @@ import { writeFileSync as writeFileSync2 } from "fs";
1540
1794
  import { resolve as resolve2, dirname as dirname5 } from "path";
1541
1795
  import { mkdirSync as mkdirSync3 } from "fs";
1542
1796
  function createGetNodeByIdCommand() {
1543
- 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) => {
1544
1798
  await handleGetNodeById(options);
1545
1799
  });
1546
1800
  }
@@ -1566,7 +1820,7 @@ async function handleGetNodeById(options) {
1566
1820
  const outputPath = resolve2(options.output);
1567
1821
  const outputDir = dirname5(outputPath);
1568
1822
  mkdirSync3(outputDir, { recursive: true });
1569
- const jsonContent = JSON.stringify(outputData, null, 2);
1823
+ const jsonContent = JSON.stringify(outputData, null, options.pretty ? 2 : 0);
1570
1824
  writeFileSync2(outputPath, jsonContent, "utf-8");
1571
1825
  const size = jsonContent.length;
1572
1826
  const sizeKB = (size / 1024).toFixed(2);
@@ -1574,6 +1828,7 @@ async function handleGetNodeById(options) {
1574
1828
  console.log(`\u8282\u70B9 ID: ${options.nodeId}`);
1575
1829
  console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
1576
1830
  console.log(`\u8282\u70B9\u6DF1\u5EA6: ${params.maxDepth}`);
1831
+ console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
1577
1832
  if (!options.raw) {
1578
1833
  console.log(`\u6570\u636E\u6A21\u5F0F: \u7CBE\u7B80\u6A21\u5F0F (\u4F7F\u7528 --raw \u83B7\u53D6\u5B8C\u6574\u6570\u636E)`);
1579
1834
  }
@@ -1591,7 +1846,7 @@ import { writeFileSync as writeFileSync3 } from "fs";
1591
1846
  import { resolve as resolve3, dirname as dirname6 } from "path";
1592
1847
  import { mkdirSync as mkdirSync4 } from "fs";
1593
1848
  function createGetNodeByLinkCommand() {
1594
- 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) => {
1595
1850
  await handleGetNodeByLink(options);
1596
1851
  });
1597
1852
  }
@@ -1641,7 +1896,7 @@ async function handleGetNodeByLink(options) {
1641
1896
  const outputPath = resolve3(options.output);
1642
1897
  const outputDir = dirname6(outputPath);
1643
1898
  mkdirSync4(outputDir, { recursive: true });
1644
- const jsonContent = JSON.stringify(outputData, null, 2);
1899
+ const jsonContent = JSON.stringify(outputData, null, options.pretty ? 2 : 0);
1645
1900
  writeFileSync3(outputPath, jsonContent, "utf-8");
1646
1901
  const size = jsonContent.length;
1647
1902
  const sizeKB = (size / 1024).toFixed(2);
@@ -1657,6 +1912,7 @@ async function handleGetNodeByLink(options) {
1657
1912
  }
1658
1913
  console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
1659
1914
  console.log(`\u904D\u5386\u6DF1\u5EA6: ${options.maxDepth || "1"}`);
1915
+ console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
1660
1916
  if (!options.raw) {
1661
1917
  console.log(`\u6570\u636E\u6A21\u5F0F: \u7CBE\u7B80\u6A21\u5F0F (\u4F7F\u7528 --raw \u83B7\u53D6\u5B8C\u6574\u6570\u636E)`);
1662
1918
  }
@@ -1678,7 +1934,7 @@ import { writeFileSync as writeFileSync4 } from "fs";
1678
1934
  import { resolve as resolve4, dirname as dirname7 } from "path";
1679
1935
  import { mkdirSync as mkdirSync5 } from "fs";
1680
1936
  function createGetAllNodesCommand() {
1681
- 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) => {
1682
1938
  await handleGetAllNodes(options);
1683
1939
  });
1684
1940
  }
@@ -1698,7 +1954,7 @@ async function handleGetAllNodes(options) {
1698
1954
  const outputPath = resolve4(options.output);
1699
1955
  const outputDir = dirname7(outputPath);
1700
1956
  mkdirSync5(outputDir, { recursive: true });
1701
- const jsonContent = JSON.stringify(outputData, null, 2);
1957
+ const jsonContent = JSON.stringify(outputData, null, options.pretty ? 2 : 0);
1702
1958
  writeFileSync4(outputPath, jsonContent, "utf-8");
1703
1959
  const size = jsonContent.length;
1704
1960
  const sizeKB = (size / 1024).toFixed(2);
@@ -1707,6 +1963,7 @@ async function handleGetAllNodes(options) {
1707
1963
  console.log(`\u8282\u70B9\u6570\u91CF: ${nodeCount}`);
1708
1964
  console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
1709
1965
  console.log(`\u8282\u70B9\u6DF1\u5EA6: ${params.maxDepth}`);
1966
+ console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
1710
1967
  if (!options.raw) {
1711
1968
  console.log(`\u6570\u636E\u6A21\u5F0F: \u7CBE\u7B80\u6A21\u5F0F (\u4F7F\u7528 --raw \u83B7\u53D6\u5B8C\u6574\u6570\u636E)`);
1712
1969
  }
@@ -1906,7 +2163,7 @@ async function convertSvgToVector(svgPath, outputDir) {
1906
2163
  // src/cli/commands/execute-code.ts
1907
2164
  import { Command as Command6 } from "commander";
1908
2165
  function createExecuteCodeCommand() {
1909
- 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) => {
1910
2167
  await handleExecuteCode(code, options);
1911
2168
  });
1912
2169
  }
@@ -1939,7 +2196,7 @@ async function handleExecuteCode(code, options) {
1939
2196
  if (result === null || result === void 0) {
1940
2197
  console.log("\u6267\u884C\u5B8C\u6210\uFF08\u65E0\u8FD4\u56DE\u503C\uFF09");
1941
2198
  } else if (typeof result === "object") {
1942
- console.log(JSON.stringify(result, null, 2));
2199
+ console.log(JSON.stringify(result, null, options.pretty ? 2 : 0));
1943
2200
  } else {
1944
2201
  console.log(result);
1945
2202
  }
@@ -1958,7 +2215,7 @@ import { resolve as resolve6, dirname as dirname9 } from "path";
1958
2215
  import { mkdirSync as mkdirSync7 } from "fs";
1959
2216
  import { tmpdir as tmpdir2 } from "os";
1960
2217
  function createGetAllPagesCommand() {
1961
- 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) => {
1962
2219
  await handleGetAllPages(options);
1963
2220
  });
1964
2221
  }
@@ -2004,7 +2261,7 @@ async function handleGetAllPages(options) {
2004
2261
  }
2005
2262
  const outputDir = dirname9(outputPath);
2006
2263
  mkdirSync7(outputDir, { recursive: true });
2007
- const jsonContent = JSON.stringify(data, null, 2);
2264
+ const jsonContent = JSON.stringify(data, null, options.pretty ? 2 : 0);
2008
2265
  writeFileSync6(outputPath, jsonContent, "utf-8");
2009
2266
  const size = jsonContent.length;
2010
2267
  const sizeKB = (size / 1024).toFixed(2);
@@ -2012,6 +2269,7 @@ async function handleGetAllPages(options) {
2012
2269
  console.log(`\u6587\u6863\u540D\u79F0: ${data.documentName}`);
2013
2270
  console.log(`\u9875\u9762\u6570\u91CF: ${data.totalCount}`);
2014
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"}`);
2015
2273
  } catch (error) {
2016
2274
  console.error(`\u9519\u8BEF: ${error instanceof Error ? error.message : error}`);
2017
2275
  process.exit(1);
@@ -2026,7 +2284,7 @@ import { writeFileSync as writeFileSync7 } from "fs";
2026
2284
  import { resolve as resolve7, dirname as dirname10 } from "path";
2027
2285
  import { mkdirSync as mkdirSync8 } from "fs";
2028
2286
  function createGetNodeForSpaceCommand() {
2029
- 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) => {
2030
2288
  await handleGetNodeForSpace(options);
2031
2289
  });
2032
2290
  }
@@ -2105,7 +2363,7 @@ async function handleGetNodeForSpace(options) {
2105
2363
  const outputPath = resolve7(options.output);
2106
2364
  const outputDir = dirname10(outputPath);
2107
2365
  mkdirSync8(outputDir, { recursive: true });
2108
- const jsonContent = JSON.stringify(spaceData, null, 2);
2366
+ const jsonContent = JSON.stringify(spaceData, null, options.pretty ? 2 : 0);
2109
2367
  writeFileSync7(outputPath, jsonContent, "utf-8");
2110
2368
  const size = jsonContent.length;
2111
2369
  const sizeKB = (size / 1024).toFixed(2);
@@ -2123,6 +2381,7 @@ async function handleGetNodeForSpace(options) {
2123
2381
  }
2124
2382
  console.log(`\u6570\u636E\u5927\u5C0F: ${size.toLocaleString()} \u5B57\u7B26 (\u7EA6 ${sizeKB} KB)`);
2125
2383
  console.log(`\u8282\u70B9\u6DF1\u5EA6: ${maxDepth}`);
2384
+ console.log(`\u8F93\u51FA\u683C\u5F0F: ${options.pretty ? "\u683C\u5F0F\u5316" : "\u538B\u7F29"}`);
2126
2385
  console.log(`\u6570\u636E\u6A21\u5F0F: \u7A7A\u95F4\u4FE1\u606F (\u4EC5 id, name, x, y, width, height)`);
2127
2386
  } catch (error) {
2128
2387
  if (error instanceof MGError) {
@@ -2136,8 +2395,229 @@ async function handleGetNodeForSpace(options) {
2136
2395
  }
2137
2396
  }
2138
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
+
2139
2619
  // src/cli/index.ts
2140
- var program = new Command9();
2620
+ var program = new Command12();
2141
2621
  program.name("mg-cli").description("MasterGo CLI \u5DE5\u5177 - \u7528\u4E8E Claude Code \u4E0E MasterGo \u901A\u4FE1").version("1.0.0");
2142
2622
  program.addCommand(createServerCommand());
2143
2623
  program.addCommand(createGetNodeByIdCommand());
@@ -2147,5 +2627,8 @@ program.addCommand(createExportImageCommand());
2147
2627
  program.addCommand(createExecuteCodeCommand());
2148
2628
  program.addCommand(createGetAllPagesCommand());
2149
2629
  program.addCommand(createGetNodeForSpaceCommand());
2630
+ program.addCommand(createListExtensionsCommand());
2631
+ program.addCommand(createOpenPageCommand());
2632
+ program.addCommand(createNavigateToNodeCommand());
2150
2633
  program.parse();
2151
2634
  //# sourceMappingURL=cli.js.map