@appthen/cli 1.2.2 → 1.2.3

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/index.js CHANGED
@@ -29,6 +29,7 @@ var prettier = require('prettier');
29
29
  var fs$2 = require('fs-extra');
30
30
  var io = require('socket.io-client');
31
31
  var fs$3 = require('fs/promises');
32
+ var chokidar = require('chokidar');
32
33
  var whatwgUrl = require('whatwg-url');
33
34
 
34
35
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
@@ -80,6 +81,7 @@ var fs__default$1 = /*#__PURE__*/_interopDefaultLegacy(fs$2);
80
81
  var fs__namespace$1 = /*#__PURE__*/_interopNamespace(fs$2);
81
82
  var io__default = /*#__PURE__*/_interopDefaultLegacy(io);
82
83
  var fs__default$2 = /*#__PURE__*/_interopDefaultLegacy(fs$3);
84
+ var chokidar__default = /*#__PURE__*/_interopDefaultLegacy(chokidar);
83
85
  var whatwgUrl__default = /*#__PURE__*/_interopDefaultLegacy(whatwgUrl);
84
86
 
85
87
  /******************************************************************************
@@ -285,6 +287,9 @@ function removeDir(_path) {
285
287
  }
286
288
  }
287
289
 
290
+ let urlAlphabet =
291
+ 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict';
292
+
288
293
  const POOL_SIZE_MULTIPLIER = 128;
289
294
  let pool, poolOffset;
290
295
  let fillPool = bytes => {
@@ -319,6 +324,14 @@ let customRandom = (alphabet, defaultSize, getRandom) => {
319
324
  };
320
325
  let customAlphabet = (alphabet, size = 21) =>
321
326
  customRandom(alphabet, size, random);
327
+ let nanoid$1 = (size = 21) => {
328
+ fillPool((size -= 0));
329
+ let id = '';
330
+ for (let i = poolOffset - size; i < poolOffset; i++) {
331
+ id += urlAlphabet[pool[i] & 63];
332
+ }
333
+ return id
334
+ };
322
335
 
323
336
  require('base-64').encode;
324
337
  var svgToBase64 = function (svgString) {
@@ -40679,6 +40692,10 @@ function regExpEscape (s) {
40679
40692
  var ShadowSpace = /** @class */ (function () {
40680
40693
  function ShadowSpace(config) {
40681
40694
  this.contentCache = new Map(); // 内容缓存
40695
+ // 🆕 文件监听相关
40696
+ this.watcher = null;
40697
+ this.changeListeners = new Set();
40698
+ this.isWatching = false;
40682
40699
  this.config = __assign({ spaceId: 'default', ignorePatterns: [
40683
40700
  'node_modules/**',
40684
40701
  '.git/**',
@@ -40719,6 +40736,8 @@ var ShadowSpace = /** @class */ (function () {
40719
40736
  '.php',
40720
40737
  '.rb',
40721
40738
  '.swift',
40739
+ '.flow',
40740
+ '.draw',
40722
40741
  '.kt',
40723
40742
  '.data', // 添加 .data 扩展名支持
40724
40743
  ] }, config);
@@ -40798,7 +40817,7 @@ var ShadowSpace = /** @class */ (function () {
40798
40817
  ShadowSpace.prototype.syncFromEditor = function (projectFiles) {
40799
40818
  var _a;
40800
40819
  return __awaiter(this, void 0, void 0, function () {
40801
- var newFiles, projectFiles_1, projectFiles_1_1, file, localHash, size, now, e_1_1, _b, _c, _d, filePath, fileEntry, allFiles, totalFilesCount, totalSizeSum;
40820
+ var newFiles, projectFiles_1, projectFiles_1_1, file, size, now, fullPath, writtenContent, localHash, remoteHash, e_1_1, _b, _c, _d, filePath, fileEntry, allFiles, totalFilesCount, totalSizeSum;
40802
40821
  var e_1, _e, e_2, _f;
40803
40822
  return __generator(this, function (_g) {
40804
40823
  switch (_g.label) {
@@ -40807,61 +40826,69 @@ var ShadowSpace = /** @class */ (function () {
40807
40826
  newFiles = {};
40808
40827
  _g.label = 1;
40809
40828
  case 1:
40810
- _g.trys.push([1, 6, 7, 8]);
40829
+ _g.trys.push([1, 7, 8, 9]);
40811
40830
  projectFiles_1 = __values(projectFiles), projectFiles_1_1 = projectFiles_1.next();
40812
40831
  _g.label = 2;
40813
40832
  case 2:
40814
- if (!!projectFiles_1_1.done) return [3 /*break*/, 5];
40833
+ if (!!projectFiles_1_1.done) return [3 /*break*/, 6];
40815
40834
  file = projectFiles_1_1.value;
40816
40835
  if (this.shouldIgnoreFile(file.path)) {
40817
40836
  console.log("[ShadowSpace] \u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(file.path));
40818
- return [3 /*break*/, 4];
40837
+ return [3 /*break*/, 5];
40819
40838
  }
40820
- localHash = this.calculateHash(file.content);
40821
40839
  size = Buffer.byteLength(file.content, 'utf8');
40822
40840
  now = Date.now();
40823
40841
  // 记录空内容文件
40824
40842
  if (file.content === '') {
40825
40843
  console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u7A7A\u5185\u5BB9\u6587\u4EF6: ".concat(file.path, " (size: ").concat(size, ")"));
40826
40844
  }
40845
+ // 写入本地文件
40846
+ return [4 /*yield*/, this.writeLocalFile(file.path, file.content)];
40847
+ case 3:
40848
+ // 写入本地文件
40849
+ _g.sent();
40850
+ fullPath = path__default["default"].join(this.config.projectRoot, file.path);
40851
+ return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
40852
+ case 4:
40853
+ writtenContent = _g.sent();
40854
+ localHash = this.calculateHash(writtenContent);
40855
+ remoteHash = file.hash || localHash;
40827
40856
  newFiles[file.path] = {
40828
40857
  path: file.path,
40829
40858
  hash: localHash,
40830
- remoteHash: file.hash || localHash,
40859
+ remoteHash: remoteHash,
40831
40860
  size: size,
40832
40861
  lastSyncTime: now,
40833
40862
  lastModified: file.modify || now,
40834
40863
  version: ((_a = this.state.files[file.path]) === null || _a === void 0 ? void 0 : _a.version) + 1 || 1,
40835
40864
  mtime: now,
40865
+ remoteModified: true,
40866
+ remoteModifiedTime: now,
40836
40867
  };
40837
40868
  console.log("[ShadowSpace] \u540C\u6B65\u6587\u4EF6: ".concat(file.path), {
40869
+ remoteHash: remoteHash.substring(0, 16),
40838
40870
  localHash: localHash.substring(0, 16),
40839
- remoteHash: (file.hash || localHash).substring(0, 16),
40840
40871
  size: size,
40872
+ version: newFiles[file.path].version,
40841
40873
  });
40842
- // 写入本地文件
40843
- return [4 /*yield*/, this.writeLocalFile(file.path, file.content)];
40844
- case 3:
40845
- // 写入本地文件
40846
- _g.sent();
40847
40874
  // 缓存内容用于diff
40848
- this.contentCache.set(file.path, file.content);
40849
- _g.label = 4;
40850
- case 4:
40875
+ this.contentCache.set(file.path, writtenContent);
40876
+ _g.label = 5;
40877
+ case 5:
40851
40878
  projectFiles_1_1 = projectFiles_1.next();
40852
40879
  return [3 /*break*/, 2];
40853
- case 5: return [3 /*break*/, 8];
40854
- case 6:
40880
+ case 6: return [3 /*break*/, 9];
40881
+ case 7:
40855
40882
  e_1_1 = _g.sent();
40856
40883
  e_1 = { error: e_1_1 };
40857
- return [3 /*break*/, 8];
40858
- case 7:
40884
+ return [3 /*break*/, 9];
40885
+ case 8:
40859
40886
  try {
40860
40887
  if (projectFiles_1_1 && !projectFiles_1_1.done && (_e = projectFiles_1.return)) _e.call(projectFiles_1);
40861
40888
  }
40862
40889
  finally { if (e_1) throw e_1.error; }
40863
40890
  return [7 /*endfinally*/];
40864
- case 8:
40891
+ case 9:
40865
40892
  try {
40866
40893
  // 合并文件记录,而不是替换
40867
40894
  for (_b = __values(Object.entries(newFiles)), _c = _b.next(); !_c.done; _c = _b.next()) {
@@ -40887,11 +40914,11 @@ var ShadowSpace = /** @class */ (function () {
40887
40914
  console.log("[ShadowSpace] \u66F4\u65B0\u540E\u7684\u6587\u4EF6\u7EDF\u8BA1:", {
40888
40915
  totalFiles: totalFilesCount,
40889
40916
  totalSize: totalSizeSum,
40890
- fileList: Object.keys(this.state.files),
40917
+ // fileList: Object.keys(this.state.files),
40891
40918
  });
40892
40919
  this.state.lastUpdateTime = Date.now();
40893
40920
  return [4 /*yield*/, this.saveState()];
40894
- case 9:
40921
+ case 10:
40895
40922
  _g.sent();
40896
40923
  console.log("\u5F71\u5B50\u7A7A\u95F4\u540C\u6B65\u5B8C\u6210: ".concat(this.state.metadata.totalFiles, " \u4E2A\u6587\u4EF6"));
40897
40924
  return [2 /*return*/];
@@ -40990,54 +41017,62 @@ var ShadowSpace = /** @class */ (function () {
40990
41017
  * 检测本地文件系统与影子空间的差异
40991
41018
  */
40992
41019
  ShadowSpace.prototype.detectChanges = function () {
41020
+ var _a;
40993
41021
  return __awaiter(this, void 0, void 0, function () {
40994
- var changes, _a, _b, _c, filePath, shadowEntry, localFilePath, localContent, localHash, _d, _e, _f, shadowContent, _g, _h, error_2, shadowContent, e_3_1, localFiles, localFiles_1, localFiles_1_1, localFile;
40995
- var e_3, _j, _k, _l, e_4, _m;
40996
- return __generator(this, function (_o) {
40997
- switch (_o.label) {
41022
+ var changes, _b, _c, _d, filePath, shadowEntry, localFilePath, localContent, localHash, _e, _f, _g, shadowContent, _h, _j, error_2, shadowContent, e_3_1, localFiles, localFiles_1, localFiles_1_1, localFile;
41023
+ var e_3, _k, _l, _m, e_4, _o;
41024
+ return __generator(this, function (_p) {
41025
+ switch (_p.label) {
40998
41026
  case 0:
40999
41027
  changes = [];
41000
- _o.label = 1;
41028
+ _p.label = 1;
41001
41029
  case 1:
41002
- _o.trys.push([1, 16, 17, 18]);
41003
- _a = __values(Object.entries(this.state.files)), _b = _a.next();
41004
- _o.label = 2;
41030
+ _p.trys.push([1, 16, 17, 18]);
41031
+ _b = __values(Object.entries(this.state.files)), _c = _b.next();
41032
+ _p.label = 2;
41005
41033
  case 2:
41006
- if (!!_b.done) return [3 /*break*/, 15];
41007
- _c = __read(_b.value, 2), filePath = _c[0], shadowEntry = _c[1];
41034
+ if (!!_c.done) return [3 /*break*/, 15];
41035
+ _d = __read(_c.value, 2), filePath = _d[0], shadowEntry = _d[1];
41008
41036
  localFilePath = path__default["default"].join(this.config.projectRoot, filePath);
41009
- _o.label = 3;
41037
+ _p.label = 3;
41010
41038
  case 3:
41011
- _o.trys.push([3, 11, , 14]);
41039
+ _p.trys.push([3, 11, , 14]);
41012
41040
  return [4 /*yield*/, fs__default$1["default"].readFile(localFilePath, 'utf8')];
41013
41041
  case 4:
41014
- localContent = _o.sent();
41042
+ localContent = _p.sent();
41015
41043
  localHash = this.calculateHash(localContent);
41016
41044
  if (!(localHash !== shadowEntry.hash)) return [3 /*break*/, 10];
41045
+ console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4: ".concat(filePath), {
41046
+ localHash: localHash.substring(0, 16),
41047
+ shadowHash: shadowEntry.hash.substring(0, 16),
41048
+ remoteHash: ((_a = shadowEntry.remoteHash) === null || _a === void 0 ? void 0 : _a.substring(0, 16)) || 'undefined',
41049
+ remoteModified: shadowEntry.remoteModified || false,
41050
+ version: shadowEntry.version,
41051
+ });
41017
41052
  if (!shadowEntry.remoteModified) return [3 /*break*/, 7];
41018
41053
  // 如果是远程修改,先更新影子空间记录并清除远程修改标记
41019
41054
  console.log("\u68C0\u6D4B\u5230\u8FDC\u7A0B\u4FEE\u6539\u6587\u4EF6\u7684\u672C\u5730\u53D8\u5316: ".concat(filePath));
41020
41055
  // 更新影子空间记录
41021
- _d = this.state.files;
41022
- _e = filePath;
41023
- _f = [__assign({}, shadowEntry)];
41024
- _k = { hash: localHash };
41056
+ _e = this.state.files;
41057
+ _f = filePath;
41058
+ _g = [__assign({}, shadowEntry)];
41059
+ _l = { hash: localHash };
41025
41060
  return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
41026
41061
  case 5:
41027
- _k.size = (_o.sent()).size, _k.lastSyncTime = Date.now(), _k.version = shadowEntry.version + 1;
41062
+ _l.size = (_p.sent()).size, _l.lastSyncTime = Date.now(), _l.version = shadowEntry.version + 1;
41028
41063
  return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
41029
41064
  case 6:
41030
41065
  // 更新影子空间记录
41031
- _d[_e] = __assign.apply(void 0, _f.concat([(_k.mtime = (_o.sent()).mtimeMs, _k.remoteModified = false, _k)]));
41066
+ _e[_f] = __assign.apply(void 0, _g.concat([(_l.mtime = (_p.sent()).mtimeMs, _l.remoteModified = false, _l)]));
41032
41067
  // 如果本地内容与最初的远程内容不同,则认为是本地修改
41033
41068
  // 这里我们简化处理:任何在远程修改基础上的本地变化都视为本地修改
41034
41069
  console.log("\u6587\u4EF6 ".concat(filePath, " \u5728\u8FDC\u7A0B\u4FEE\u6539\u57FA\u7840\u4E0A\u53D1\u751F\u4E86\u672C\u5730\u53D8\u5316\uFF0C\u6807\u8BB0\u4E3A\u672C\u5730\u4FEE\u6539"));
41035
- _o.label = 7;
41070
+ _p.label = 7;
41036
41071
  case 7: return [4 /*yield*/, this.getShadowContent(filePath)];
41037
41072
  case 8:
41038
- shadowContent = _o.sent();
41039
- _h = (_g = changes).push;
41040
- _l = {
41073
+ shadowContent = _p.sent();
41074
+ _j = (_h = changes).push;
41075
+ _m = {
41041
41076
  id: this.generateId(),
41042
41077
  action: 'modify',
41043
41078
  path: filePath,
@@ -41045,21 +41080,21 @@ var ShadowSpace = /** @class */ (function () {
41045
41080
  };
41046
41081
  return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
41047
41082
  case 9:
41048
- _h.apply(_g, [(_l.timestamp = (_o.sent()).mtime.getTime(),
41049
- _l.diff = {
41083
+ _j.apply(_h, [(_m.timestamp = (_p.sent()).mtime.getTime(),
41084
+ _m.diff = {
41050
41085
  before: shadowContent,
41051
41086
  after: localContent,
41052
41087
  },
41053
- _l.projectId = this.state.projectId,
41054
- _l)]);
41055
- _o.label = 10;
41088
+ _m.projectId = this.state.projectId,
41089
+ _m)]);
41090
+ _p.label = 10;
41056
41091
  case 10: return [3 /*break*/, 14];
41057
41092
  case 11:
41058
- error_2 = _o.sent();
41093
+ error_2 = _p.sent();
41059
41094
  if (!(error_2.code === 'ENOENT')) return [3 /*break*/, 13];
41060
41095
  return [4 /*yield*/, this.getShadowContent(filePath)];
41061
41096
  case 12:
41062
- shadowContent = _o.sent();
41097
+ shadowContent = _p.sent();
41063
41098
  changes.push({
41064
41099
  id: this.generateId(),
41065
41100
  action: 'delete',
@@ -41072,25 +41107,25 @@ var ShadowSpace = /** @class */ (function () {
41072
41107
  },
41073
41108
  projectId: this.state.projectId,
41074
41109
  });
41075
- _o.label = 13;
41110
+ _p.label = 13;
41076
41111
  case 13: return [3 /*break*/, 14];
41077
41112
  case 14:
41078
- _b = _a.next();
41113
+ _c = _b.next();
41079
41114
  return [3 /*break*/, 2];
41080
41115
  case 15: return [3 /*break*/, 18];
41081
41116
  case 16:
41082
- e_3_1 = _o.sent();
41117
+ e_3_1 = _p.sent();
41083
41118
  e_3 = { error: e_3_1 };
41084
41119
  return [3 /*break*/, 18];
41085
41120
  case 17:
41086
41121
  try {
41087
- if (_b && !_b.done && (_j = _a.return)) _j.call(_a);
41122
+ if (_c && !_c.done && (_k = _b.return)) _k.call(_b);
41088
41123
  }
41089
41124
  finally { if (e_3) throw e_3.error; }
41090
41125
  return [7 /*endfinally*/];
41091
41126
  case 18: return [4 /*yield*/, this.scanLocalFiles()];
41092
41127
  case 19:
41093
- localFiles = _o.sent();
41128
+ localFiles = _p.sent();
41094
41129
  try {
41095
41130
  for (localFiles_1 = __values(localFiles), localFiles_1_1 = localFiles_1.next(); !localFiles_1_1.done; localFiles_1_1 = localFiles_1.next()) {
41096
41131
  localFile = localFiles_1_1.value;
@@ -41113,7 +41148,7 @@ var ShadowSpace = /** @class */ (function () {
41113
41148
  catch (e_4_1) { e_4 = { error: e_4_1 }; }
41114
41149
  finally {
41115
41150
  try {
41116
- if (localFiles_1_1 && !localFiles_1_1.done && (_m = localFiles_1.return)) _m.call(localFiles_1);
41151
+ if (localFiles_1_1 && !localFiles_1_1.done && (_o = localFiles_1.return)) _o.call(localFiles_1);
41117
41152
  }
41118
41153
  finally { if (e_4) throw e_4.error; }
41119
41154
  }
@@ -41243,38 +41278,40 @@ var ShadowSpace = /** @class */ (function () {
41243
41278
  * 当编辑器通过WebSocket修改文件后调用此方法
41244
41279
  */
41245
41280
  ShadowSpace.prototype.markAsRemoteModified = function (filePaths) {
41281
+ var _a;
41246
41282
  return __awaiter(this, void 0, void 0, function () {
41247
- var now, hasChanges, filePaths_1, filePaths_1_1, filePath, fullPath, stats, content, hash, existingFile, error_4, e_6_1;
41248
- var e_6, _a;
41249
- return __generator(this, function (_b) {
41250
- switch (_b.label) {
41283
+ var now, hasChanges, filePaths_1, filePaths_1_1, filePath, fullPath, stats, content, hash, existingFile, remoteHash, error_4, e_6_1;
41284
+ var e_6, _b;
41285
+ return __generator(this, function (_c) {
41286
+ switch (_c.label) {
41251
41287
  case 0:
41252
41288
  now = Date.now();
41253
41289
  hasChanges = false;
41254
- _b.label = 1;
41290
+ _c.label = 1;
41255
41291
  case 1:
41256
- _b.trys.push([1, 9, 10, 11]);
41292
+ _c.trys.push([1, 9, 10, 11]);
41257
41293
  filePaths_1 = __values(filePaths), filePaths_1_1 = filePaths_1.next();
41258
- _b.label = 2;
41294
+ _c.label = 2;
41259
41295
  case 2:
41260
41296
  if (!!filePaths_1_1.done) return [3 /*break*/, 8];
41261
41297
  filePath = filePaths_1_1.value;
41262
41298
  fullPath = path__default["default"].resolve(this.config.projectRoot, filePath);
41263
- _b.label = 3;
41299
+ _c.label = 3;
41264
41300
  case 3:
41265
- _b.trys.push([3, 6, , 7]);
41301
+ _c.trys.push([3, 6, , 7]);
41266
41302
  return [4 /*yield*/, fs__default$1["default"].stat(fullPath)];
41267
41303
  case 4:
41268
- stats = _b.sent();
41304
+ stats = _c.sent();
41269
41305
  return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
41270
41306
  case 5:
41271
- content = _b.sent();
41307
+ content = _c.sent();
41272
41308
  hash = this.calculateHash(content);
41273
41309
  existingFile = this.state.files[filePath];
41310
+ remoteHash = (existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) || hash;
41274
41311
  this.state.files[filePath] = {
41275
41312
  path: filePath,
41276
41313
  hash: hash,
41277
- remoteHash: (existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) || hash,
41314
+ remoteHash: remoteHash,
41278
41315
  size: stats.size,
41279
41316
  lastSyncTime: now,
41280
41317
  lastModified: now,
@@ -41284,10 +41321,16 @@ var ShadowSpace = /** @class */ (function () {
41284
41321
  remoteModifiedTime: now,
41285
41322
  };
41286
41323
  hasChanges = true;
41287
- console.log("\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ".concat(filePath, " (\u7248\u672C ").concat(this.state.files[filePath].version, ")"));
41324
+ console.log("[ShadowSpace] \u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ".concat(filePath), {
41325
+ 版本: this.state.files[filePath].version,
41326
+ hash: hash.substring(0, 16),
41327
+ remoteHash: remoteHash.substring(0, 16),
41328
+ 旧remoteHash: ((_a = existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) === null || _a === void 0 ? void 0 : _a.substring(0, 16)) || 'undefined',
41329
+ remoteHashChanged: (existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) !== remoteHash,
41330
+ });
41288
41331
  return [3 /*break*/, 7];
41289
41332
  case 6:
41290
- error_4 = _b.sent();
41333
+ error_4 = _c.sent();
41291
41334
  console.warn("\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25 ".concat(filePath, ":"), error_4);
41292
41335
  return [3 /*break*/, 7];
41293
41336
  case 7:
@@ -41295,12 +41338,12 @@ var ShadowSpace = /** @class */ (function () {
41295
41338
  return [3 /*break*/, 2];
41296
41339
  case 8: return [3 /*break*/, 11];
41297
41340
  case 9:
41298
- e_6_1 = _b.sent();
41341
+ e_6_1 = _c.sent();
41299
41342
  e_6 = { error: e_6_1 };
41300
41343
  return [3 /*break*/, 11];
41301
41344
  case 10:
41302
41345
  try {
41303
- if (filePaths_1_1 && !filePaths_1_1.done && (_a = filePaths_1.return)) _a.call(filePaths_1);
41346
+ if (filePaths_1_1 && !filePaths_1_1.done && (_b = filePaths_1.return)) _b.call(filePaths_1);
41304
41347
  }
41305
41348
  finally { if (e_6) throw e_6.error; }
41306
41349
  return [7 /*endfinally*/];
@@ -41309,9 +41352,9 @@ var ShadowSpace = /** @class */ (function () {
41309
41352
  this.updateMetadata();
41310
41353
  return [4 /*yield*/, this.saveState()];
41311
41354
  case 12:
41312
- _b.sent();
41355
+ _c.sent();
41313
41356
  console.log("\u5DF2\u6807\u8BB0 ".concat(filePaths.length, " \u4E2A\u6587\u4EF6\u4E3A\u8FDC\u7A0B\u4FEE\u6539"));
41314
- _b.label = 13;
41357
+ _c.label = 13;
41315
41358
  case 13: return [2 /*return*/];
41316
41359
  }
41317
41360
  });
@@ -41614,44 +41657,27 @@ var ShadowSpace = /** @class */ (function () {
41614
41657
  return "change_".concat(Date.now(), "_").concat(Math.random().toString(36).substr(2, 9));
41615
41658
  };
41616
41659
  ShadowSpace.prototype.shouldIgnoreFile = function (filePath) {
41660
+ // console.log(`[ShadowSpace] shouldIgnoreFile 检查: "${filePath}"`);
41617
41661
  var e_10, _a;
41618
- console.log("[ShadowSpace] shouldIgnoreFile \u68C0\u67E5: ".concat(filePath), {
41619
- ignorePatterns: this.config.ignorePatterns,
41620
- includeExtensions: this.config.includeExtensions,
41621
- });
41622
41662
  // 特殊处理:过滤掉特定的系统文件
41623
41663
  var fileName = filePath.split('/').pop() || '';
41624
41664
  if (fileName === '.dirty_files.json') {
41625
- console.log("[ShadowSpace] \u7CFB\u7EDF\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
41626
41665
  return true;
41627
41666
  }
41628
41667
  if (fileName === 'assets.json') {
41629
- console.log("[ShadowSpace] \u7CFB\u7EDF\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
41630
41668
  return true;
41631
41669
  }
41632
41670
  if (fileName === 'project.json') {
41633
- console.log("[ShadowSpace] \u7CFB\u7EDF\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
41634
41671
  return true;
41635
41672
  }
41636
41673
  if (fileName.endsWith('.doc')) {
41637
- console.log("[ShadowSpace] .doc\u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(filePath));
41638
41674
  return true;
41639
41675
  }
41640
- // 目录白名单检查:只同步指定的目录
41676
+ // 🔥 目录白名单检查:简化逻辑,允许 src/ 和 docs/ 下的所有文件
41677
+ var isInSrc = filePath.startsWith('src/');
41641
41678
  var isInDocs = filePath.startsWith('docs/');
41642
- var isInSrcPages = filePath.startsWith('src/pages/');
41643
- var isInSrcModules = filePath.startsWith('src/modules/');
41644
- var isInSrcTypes = filePath.startsWith('src/types/');
41645
- var isInSrcUtils = filePath.startsWith('src/utils/');
41646
- var isInSrcComponents = filePath.startsWith('src/components/');
41647
41679
  var isRootConfig = filePath.match(/^[^\/]+\.(json|md|yml|yaml|toml|js|ts|py|go|rs)$/);
41648
- if (!isInDocs &&
41649
- !isInSrcPages &&
41650
- !isInSrcModules &&
41651
- !isInSrcTypes &&
41652
- !isInSrcUtils &&
41653
- !isInSrcComponents &&
41654
- !isRootConfig) {
41680
+ if (!isInSrc && !isInDocs && !isRootConfig) {
41655
41681
  console.log("[ShadowSpace] \u6587\u4EF6\u4E0D\u5728\u767D\u540D\u5355\u76EE\u5F55\u4E2D: ".concat(filePath));
41656
41682
  return true;
41657
41683
  }
@@ -41686,7 +41712,7 @@ var ShadowSpace = /** @class */ (function () {
41686
41712
  return true;
41687
41713
  }
41688
41714
  }
41689
- console.log("[ShadowSpace] \u6587\u4EF6\u901A\u8FC7\u5FFD\u7565\u68C0\u67E5: ".concat(filePath));
41715
+ // console.log(`[ShadowSpace] 文件通过忽略检查: ${filePath}`);
41690
41716
  return false;
41691
41717
  };
41692
41718
  ShadowSpace.prototype.writeLocalFile = function (filePath, content) {
@@ -41851,15 +41877,328 @@ var ShadowSpace = /** @class */ (function () {
41851
41877
  var i = Math.floor(Math.log(bytes) / Math.log(k));
41852
41878
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
41853
41879
  };
41880
+ // ==================== 🆕 文件监听功能 ====================
41881
+ /**
41882
+ * 启动文件监听
41883
+ */
41884
+ ShadowSpace.prototype.startWatching = function () {
41885
+ var _this = this;
41886
+ if (this.isWatching) {
41887
+ console.log('[ShadowSpace] 文件监听已经在运行中');
41888
+ return;
41889
+ }
41890
+ console.log('[ShadowSpace] 启动文件监听...');
41891
+ console.log('[ShadowSpace] 监听目录:', this.config.projectRoot);
41892
+ try {
41893
+ // 🔥 使用轮询模式 + ignored 函数过滤
41894
+ this.watcher = chokidar__default["default"].watch(this.config.projectRoot, {
41895
+ ignored: function (filePath) {
41896
+ var relativePath = path__default["default"].relative(_this.config.projectRoot, filePath);
41897
+ // 忽略根目录本身
41898
+ if (!relativePath || relativePath === '.') {
41899
+ return true;
41900
+ }
41901
+ // 使用白名单过滤
41902
+ return _this.shouldIgnoreFile(relativePath);
41903
+ },
41904
+ persistent: true,
41905
+ ignoreInitial: true,
41906
+ usePolling: true,
41907
+ interval: 2000,
41908
+ binaryInterval: 3000,
41909
+ depth: 99,
41910
+ awaitWriteFinish: {
41911
+ stabilityThreshold: 500,
41912
+ pollInterval: 100,
41913
+ },
41914
+ });
41915
+ console.log('[ShadowSpace] chokidar.watch 已调用,等待 ready 事件...');
41916
+ }
41917
+ catch (error) {
41918
+ console.error('[ShadowSpace] 创建文件监听器失败:', error);
41919
+ return;
41920
+ }
41921
+ this.watcher
41922
+ .on('change', function (filePath) {
41923
+ _this.onFileChanged(filePath);
41924
+ })
41925
+ .on('add', function (filePath) {
41926
+ _this.onFileAdded(filePath);
41927
+ })
41928
+ .on('unlink', function (filePath) {
41929
+ _this.onFileDeleted(filePath);
41930
+ })
41931
+ .on('error', function (error) {
41932
+ console.error('[ShadowSpace] 文件监听错误:', error);
41933
+ })
41934
+ .on('ready', function () {
41935
+ _this.isWatching = true;
41936
+ console.log('[ShadowSpace] 文件监听已启动,正在监听:', _this.config.projectRoot);
41937
+ console.log('[ShadowSpace] 监听配置: 轮询模式 (interval: 2s)');
41938
+ });
41939
+ };
41940
+ /**
41941
+ * 停止文件监听
41942
+ */
41943
+ ShadowSpace.prototype.stopWatching = function () {
41944
+ return __awaiter(this, void 0, void 0, function () {
41945
+ return __generator(this, function (_a) {
41946
+ switch (_a.label) {
41947
+ case 0:
41948
+ if (!this.isWatching || !this.watcher) {
41949
+ console.log('[ShadowSpace] 文件监听未运行');
41950
+ return [2 /*return*/];
41951
+ }
41952
+ console.log('[ShadowSpace] 停止文件监听...');
41953
+ return [4 /*yield*/, this.watcher.close()];
41954
+ case 1:
41955
+ _a.sent();
41956
+ this.watcher = null;
41957
+ this.isWatching = false;
41958
+ console.log('[ShadowSpace] 文件监听已停止');
41959
+ return [2 /*return*/];
41960
+ }
41961
+ });
41962
+ });
41963
+ };
41964
+ /**
41965
+ * 添加变更事件监听器
41966
+ */
41967
+ ShadowSpace.prototype.addChangeListener = function (listener) {
41968
+ this.changeListeners.add(listener);
41969
+ };
41970
+ /**
41971
+ * 移除变更事件监听器
41972
+ */
41973
+ ShadowSpace.prototype.removeChangeListener = function (listener) {
41974
+ this.changeListeners.delete(listener);
41975
+ };
41976
+ /**
41977
+ * 触发变更事件
41978
+ */
41979
+ ShadowSpace.prototype.emitChangeEvent = function (event) {
41980
+ console.log('[ShadowSpace] 触发变更事件:', event);
41981
+ this.changeListeners.forEach(function (listener) {
41982
+ try {
41983
+ listener(event);
41984
+ }
41985
+ catch (error) {
41986
+ console.error('[ShadowSpace] 变更事件监听器执行失败:', error);
41987
+ }
41988
+ });
41989
+ };
41990
+ /**
41991
+ * 文件变更处理
41992
+ */
41993
+ ShadowSpace.prototype.onFileChanged = function (filePath) {
41994
+ return __awaiter(this, void 0, void 0, function () {
41995
+ var relativePath, shadowEntry, content, hash, stats, error_13;
41996
+ return __generator(this, function (_a) {
41997
+ switch (_a.label) {
41998
+ case 0:
41999
+ relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
42000
+ console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4: ".concat(relativePath));
42001
+ shadowEntry = this.state.files[relativePath];
42002
+ if (!(shadowEntry === null || shadowEntry === void 0 ? void 0 : shadowEntry.remoteModified)) return [3 /*break*/, 2];
42003
+ console.log("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u4FEE\u6539\u7684\u6587\u4EF6: ".concat(relativePath));
42004
+ shadowEntry.remoteModified = false; // 清除标记
42005
+ return [4 /*yield*/, this.saveState()];
42006
+ case 1:
42007
+ _a.sent();
42008
+ return [2 /*return*/];
42009
+ case 2:
42010
+ _a.trys.push([2, 5, , 6]);
42011
+ return [4 /*yield*/, fs__default$1["default"].readFile(filePath, 'utf8')];
42012
+ case 3:
42013
+ content = _a.sent();
42014
+ hash = this.calculateHash(content);
42015
+ return [4 /*yield*/, fs__default$1["default"].stat(filePath)];
42016
+ case 4:
42017
+ stats = _a.sent();
42018
+ // 🔑 推送变更事件
42019
+ this.emitChangeEvent({
42020
+ path: relativePath,
42021
+ action: 'modify',
42022
+ timestamp: Date.now(),
42023
+ source: 'local',
42024
+ hash: hash,
42025
+ size: stats.size,
42026
+ });
42027
+ return [3 /*break*/, 6];
42028
+ case 5:
42029
+ error_13 = _a.sent();
42030
+ console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u53D8\u66F4\u5931\u8D25: ".concat(relativePath), error_13);
42031
+ return [3 /*break*/, 6];
42032
+ case 6: return [2 /*return*/];
42033
+ }
42034
+ });
42035
+ });
42036
+ };
42037
+ /**
42038
+ * 文件新增处理
42039
+ */
42040
+ ShadowSpace.prototype.onFileAdded = function (filePath) {
42041
+ return __awaiter(this, void 0, void 0, function () {
42042
+ var relativePath, content, hash, stats, error_14;
42043
+ return __generator(this, function (_a) {
42044
+ switch (_a.label) {
42045
+ case 0:
42046
+ relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
42047
+ console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u65B0\u589E: ".concat(relativePath));
42048
+ _a.label = 1;
42049
+ case 1:
42050
+ _a.trys.push([1, 4, , 5]);
42051
+ return [4 /*yield*/, fs__default$1["default"].readFile(filePath, 'utf8')];
42052
+ case 2:
42053
+ content = _a.sent();
42054
+ hash = this.calculateHash(content);
42055
+ return [4 /*yield*/, fs__default$1["default"].stat(filePath)];
42056
+ case 3:
42057
+ stats = _a.sent();
42058
+ // 🔑 推送变更事件
42059
+ this.emitChangeEvent({
42060
+ path: relativePath,
42061
+ action: 'add',
42062
+ timestamp: Date.now(),
42063
+ source: 'local',
42064
+ hash: hash,
42065
+ size: stats.size,
42066
+ });
42067
+ return [3 /*break*/, 5];
42068
+ case 4:
42069
+ error_14 = _a.sent();
42070
+ console.error("[ShadowSpace] \u5904\u7406\u6587\u4EF6\u65B0\u589E\u5931\u8D25: ".concat(relativePath), error_14);
42071
+ return [3 /*break*/, 5];
42072
+ case 5: return [2 /*return*/];
42073
+ }
42074
+ });
42075
+ });
42076
+ };
42077
+ /**
42078
+ * 文件删除处理
42079
+ */
42080
+ ShadowSpace.prototype.onFileDeleted = function (filePath) {
42081
+ return __awaiter(this, void 0, void 0, function () {
42082
+ var relativePath, shadowEntry;
42083
+ return __generator(this, function (_a) {
42084
+ switch (_a.label) {
42085
+ case 0:
42086
+ relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
42087
+ console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u5220\u9664: ".concat(relativePath));
42088
+ shadowEntry = this.state.files[relativePath];
42089
+ if (!(shadowEntry === null || shadowEntry === void 0 ? void 0 : shadowEntry.remoteModified)) return [3 /*break*/, 2];
42090
+ console.log("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u5220\u9664\u7684\u6587\u4EF6: ".concat(relativePath));
42091
+ shadowEntry.remoteModified = false; // 清除标记
42092
+ return [4 /*yield*/, this.saveState()];
42093
+ case 1:
42094
+ _a.sent();
42095
+ return [2 /*return*/];
42096
+ case 2:
42097
+ // 🔑 推送变更事件
42098
+ this.emitChangeEvent({
42099
+ path: relativePath,
42100
+ action: 'delete',
42101
+ timestamp: Date.now(),
42102
+ source: 'local',
42103
+ });
42104
+ return [2 /*return*/];
42105
+ }
42106
+ });
42107
+ });
42108
+ };
42109
+ /**
42110
+ * 获取监听状态
42111
+ */
42112
+ ShadowSpace.prototype.isFileWatching = function () {
42113
+ return this.isWatching;
42114
+ };
41854
42115
  return ShadowSpace;
41855
42116
  }());
41856
42117
 
42118
+ /**
42119
+ * 变更聚合器
42120
+ * 将短时间内的多个文件变更聚合为一次批量推送,减少网络开销
42121
+ */
42122
+ var ChangeAggregator = /** @class */ (function () {
42123
+ function ChangeAggregator(spaceId, userId, handler, debounceMs) {
42124
+ if (debounceMs === void 0) { debounceMs = 500; }
42125
+ this.pendingChanges = new Map();
42126
+ this.timer = null;
42127
+ this.spaceId = spaceId;
42128
+ this.userId = userId;
42129
+ this.handler = handler;
42130
+ this.debounceMs = debounceMs;
42131
+ }
42132
+ /**
42133
+ * 添加变更
42134
+ */
42135
+ ChangeAggregator.prototype.addChange = function (change) {
42136
+ var _this = this;
42137
+ console.log("[ChangeAggregator] \u6DFB\u52A0\u53D8\u66F4: ".concat(change.path, " (").concat(change.action, ")"));
42138
+ // 使用文件路径作为 key,相同文件的多次变更只保留最后一次
42139
+ this.pendingChanges.set(change.path, change);
42140
+ // 防抖:重置定时器
42141
+ if (this.timer) {
42142
+ clearTimeout(this.timer);
42143
+ }
42144
+ this.timer = setTimeout(function () {
42145
+ _this.flush();
42146
+ }, this.debounceMs);
42147
+ };
42148
+ /**
42149
+ * 立即推送所有待处理的变更
42150
+ */
42151
+ ChangeAggregator.prototype.flush = function () {
42152
+ if (this.pendingChanges.size === 0) {
42153
+ return;
42154
+ }
42155
+ var changes = Array.from(this.pendingChanges.values());
42156
+ this.pendingChanges.clear();
42157
+ if (this.timer) {
42158
+ clearTimeout(this.timer);
42159
+ this.timer = null;
42160
+ }
42161
+ console.log("[ChangeAggregator] \u63A8\u9001\u6279\u91CF\u53D8\u66F4: ".concat(changes.length, " \u4E2A\u6587\u4EF6"));
42162
+ // 调用处理器
42163
+ try {
42164
+ this.handler({
42165
+ spaceId: this.spaceId,
42166
+ userId: this.userId,
42167
+ changes: changes,
42168
+ timestamp: Date.now(),
42169
+ });
42170
+ }
42171
+ catch (error) {
42172
+ console.error('[ChangeAggregator] 批量变更处理失败:', error);
42173
+ }
42174
+ };
42175
+ /**
42176
+ * 清理资源
42177
+ */
42178
+ ChangeAggregator.prototype.destroy = function () {
42179
+ if (this.timer) {
42180
+ clearTimeout(this.timer);
42181
+ this.timer = null;
42182
+ }
42183
+ this.pendingChanges.clear();
42184
+ };
42185
+ /**
42186
+ * 获取待处理变更数量
42187
+ */
42188
+ ChangeAggregator.prototype.getPendingCount = function () {
42189
+ return this.pendingChanges.size;
42190
+ };
42191
+ return ChangeAggregator;
42192
+ }());
42193
+
41857
42194
  /**
41858
42195
  * 影子空间WebSocket指令处理器
41859
42196
  */
41860
42197
  var ShadowSpaceCommandHandler = /** @class */ (function () {
41861
42198
  function ShadowSpaceCommandHandler(shadowSpace, socketStore) {
41862
42199
  this.currentUserId = null;
42200
+ // 🆕 变更聚合器
42201
+ this.changeAggregator = null;
41863
42202
  this.shadowSpace = shadowSpace;
41864
42203
  this.socketStore = socketStore;
41865
42204
  }
@@ -41874,11 +42213,11 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
41874
42213
  * 处理WebSocket消息
41875
42214
  */
41876
42215
  ShadowSpaceCommandHandler.prototype.handleMessage = function (data) {
41877
- var _a, _b, _c, _d, _e, _f;
42216
+ var _a, _b, _c, _d, _e, _f, _g;
41878
42217
  return __awaiter(this, void 0, void 0, function () {
41879
- var action, messageId, message, spaceInfo, requestSpaceId, result, _g, error_1, errorMessage;
41880
- return __generator(this, function (_h) {
41881
- switch (_h.label) {
42218
+ var action, messageId, message, spaceInfo, requestSpaceId, result, _h, error_1, errorMessage;
42219
+ return __generator(this, function (_j) {
42220
+ switch (_j.label) {
41882
42221
  case 0:
41883
42222
  action = data.action, messageId = data.messageId, message = data.message;
41884
42223
  console.log("[ShadowSpaceCommandHandler] \u6536\u5230\u6D88\u606F: ".concat(action), {
@@ -41904,12 +42243,12 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
41904
42243
  // 不发送响应,让其他CLI实例处理
41905
42244
  return [2 /*return*/];
41906
42245
  }
41907
- _h.label = 1;
42246
+ _j.label = 1;
41908
42247
  case 1:
41909
- _h.trys.push([1, 26, , 27]);
42248
+ _j.trys.push([1, 28, , 29]);
41910
42249
  result = void 0;
41911
- _g = action;
41912
- switch (_g) {
42250
+ _h = action;
42251
+ switch (_h) {
41913
42252
  case 'shadow-space-get-changes': return [3 /*break*/, 2];
41914
42253
  case 'shadow-space-get-file-content': return [3 /*break*/, 4];
41915
42254
  case 'shadow-space-get-files-content': return [3 /*break*/, 6];
@@ -41921,12 +42260,13 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
41921
42260
  case 'shadow-space-mark-remote-modified': return [3 /*break*/, 18];
41922
42261
  case 'shadow-space-clear-remote-flags': return [3 /*break*/, 20];
41923
42262
  case 'shadow-space-detect-changes': return [3 /*break*/, 22];
42263
+ case 'shadow-space-discard-changes': return [3 /*break*/, 24];
41924
42264
  }
41925
- return [3 /*break*/, 24];
42265
+ return [3 /*break*/, 26];
41926
42266
  case 2: return [4 /*yield*/, this.getChanges()];
41927
42267
  case 3:
41928
- result = _h.sent();
41929
- return [3 /*break*/, 25];
42268
+ result = _j.sent();
42269
+ return [3 /*break*/, 27];
41930
42270
  case 4:
41931
42271
  console.log('[ShadowSpaceCommandHandler] 获取文件内容 - message:', JSON.stringify(message, null, 2));
41932
42272
  console.log('[ShadowSpaceCommandHandler] 获取文件内容 - message.path:', message.path);
@@ -41934,57 +42274,61 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
41934
42274
  return [4 /*yield*/, this.getFileContent(((_c = message.message) === null || _c === void 0 ? void 0 : _c.path) || message.path)];
41935
42275
  case 5:
41936
42276
  // 🆕 修复:路径在 message.message.path 中
41937
- result = _h.sent();
41938
- return [3 /*break*/, 25];
42277
+ result = _j.sent();
42278
+ return [3 /*break*/, 27];
41939
42279
  case 6: return [4 /*yield*/, this.getFilesContent(((_d = message.message) === null || _d === void 0 ? void 0 : _d.paths) || message.paths)];
41940
42280
  case 7:
41941
42281
  // 🆕 修复:路径在 message.message.paths 中
41942
- result = _h.sent();
41943
- return [3 /*break*/, 25];
42282
+ result = _j.sent();
42283
+ return [3 /*break*/, 27];
41944
42284
  case 8: return [4 /*yield*/, this.applyChanges(message.changes)];
41945
42285
  case 9:
41946
- result = _h.sent();
41947
- return [3 /*break*/, 25];
42286
+ result = _j.sent();
42287
+ return [3 /*break*/, 27];
41948
42288
  case 10: return [4 /*yield*/, this.resetShadowSpace()];
41949
42289
  case 11:
41950
- result = _h.sent();
41951
- return [3 /*break*/, 25];
42290
+ result = _j.sent();
42291
+ return [3 /*break*/, 27];
41952
42292
  case 12: return [4 /*yield*/, this.getSpaceInfo()];
41953
42293
  case 13:
41954
- result = _h.sent();
41955
- return [3 /*break*/, 25];
42294
+ result = _j.sent();
42295
+ return [3 /*break*/, 27];
41956
42296
  case 14: return [4 /*yield*/, this.syncFromEditor(message.message.files)];
41957
42297
  case 15:
41958
- result = _h.sent();
41959
- return [3 /*break*/, 25];
42298
+ result = _j.sent();
42299
+ return [3 /*break*/, 27];
41960
42300
  case 16: return [4 /*yield*/, this.deleteFile(message.filePath)];
41961
42301
  case 17:
41962
- result = _h.sent();
41963
- return [3 /*break*/, 25];
42302
+ result = _j.sent();
42303
+ return [3 /*break*/, 27];
41964
42304
  case 18: return [4 /*yield*/, this.markRemoteModified(message.filePaths)];
41965
42305
  case 19:
41966
- result = _h.sent();
41967
- return [3 /*break*/, 25];
42306
+ result = _j.sent();
42307
+ return [3 /*break*/, 27];
41968
42308
  case 20: return [4 /*yield*/, this.clearRemoteFlags(message.filePaths)];
41969
42309
  case 21:
41970
- result = _h.sent();
41971
- return [3 /*break*/, 25];
42310
+ result = _j.sent();
42311
+ return [3 /*break*/, 27];
41972
42312
  case 22: return [4 /*yield*/, this.detectEditorChanges(((_e = message.message) === null || _e === void 0 ? void 0 : _e.spaceId) || message.spaceId, ((_f = message.message) === null || _f === void 0 ? void 0 : _f.files) || message.files)];
41973
42313
  case 23:
41974
- result = _h.sent();
41975
- return [3 /*break*/, 25];
41976
- case 24: throw new Error("Unknown shadow space action: ".concat(action));
42314
+ result = _j.sent();
42315
+ return [3 /*break*/, 27];
42316
+ case 24: return [4 /*yield*/, this.discardChanges(((_g = message.message) === null || _g === void 0 ? void 0 : _g.filePaths) || message.filePaths)];
41977
42317
  case 25:
42318
+ result = _j.sent();
42319
+ return [3 /*break*/, 27];
42320
+ case 26: throw new Error("Unknown shadow space action: ".concat(action));
42321
+ case 27:
41978
42322
  // 发送成功响应
41979
42323
  this.sendResponse(action, messageId, true, result);
41980
- return [3 /*break*/, 27];
41981
- case 26:
41982
- error_1 = _h.sent();
42324
+ return [3 /*break*/, 29];
42325
+ case 28:
42326
+ error_1 = _j.sent();
41983
42327
  errorMessage = error_1 instanceof Error ? error_1.message : String(error_1);
41984
42328
  console.error("Shadow space command error [".concat(action, "]:"), errorMessage);
41985
42329
  this.sendResponse(action, messageId, false, undefined, errorMessage);
41986
- return [3 /*break*/, 27];
41987
- case 27: return [2 /*return*/];
42330
+ return [3 /*break*/, 29];
42331
+ case 29: return [2 /*return*/];
41988
42332
  }
41989
42333
  });
41990
42334
  });
@@ -42253,9 +42597,10 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42253
42597
  return __awaiter(this, void 0, void 0, function () {
42254
42598
  var info;
42255
42599
  return __generator(this, function (_a) {
42256
- console.log('[ShadowSpace] 获取空间信息...');
42257
42600
  info = this.shadowSpace.getSpaceInfo();
42258
- console.log("[ShadowSpace] \u7A7A\u95F4\u4FE1\u606F: ".concat(info.fileCount, " \u4E2A\u6587\u4EF6, ").concat(info.totalSize));
42601
+ // console.log(
42602
+ // `[ShadowSpace] 空间信息: ${info.fileCount} 个文件, ${info.totalSize}`
42603
+ // );
42259
42604
  return [2 /*return*/, info];
42260
42605
  });
42261
42606
  });
@@ -42265,14 +42610,14 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42265
42610
  */
42266
42611
  ShadowSpaceCommandHandler.prototype.syncFromEditor = function (files) {
42267
42612
  return __awaiter(this, void 0, void 0, function () {
42268
- var filePaths, result;
42613
+ var result;
42269
42614
  return __generator(this, function (_a) {
42270
42615
  switch (_a.label) {
42271
42616
  case 0:
42272
42617
  console.log('[ShadowSpace] syncFromEditor 接收到的参数:', {
42273
42618
  filesType: typeof files,
42274
42619
  isArray: Array.isArray(files),
42275
- filesValue: files,
42620
+ // filesValue: files,
42276
42621
  filesLength: files === null || files === void 0 ? void 0 : files.length,
42277
42622
  });
42278
42623
  if (!Array.isArray(files)) {
@@ -42282,11 +42627,6 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42282
42627
  return [4 /*yield*/, this.shadowSpace.syncFromEditor(files)];
42283
42628
  case 1:
42284
42629
  _a.sent();
42285
- filePaths = files.map(function (f) { return f.path; });
42286
- return [4 /*yield*/, this.shadowSpace.markAsRemoteModified(filePaths)];
42287
- case 2:
42288
- _a.sent();
42289
- console.log("[ShadowSpace] \u5DF2\u6807\u8BB0 ".concat(filePaths.length, " \u4E2A\u6587\u4EF6\u4E3A\u8FDC\u7A0B\u4FEE\u6539"));
42290
42630
  result = {
42291
42631
  message: 'Sync from editor completed',
42292
42632
  fileCount: files.length,
@@ -42422,10 +42762,12 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42422
42762
  var actualMessage = (data === null || data === void 0 ? void 0 : data.message) || data;
42423
42763
  var actualMessageId = actualMessage === null || actualMessage === void 0 ? void 0 : actualMessage.messageId;
42424
42764
  var actualAction = actualMessage === null || actualMessage === void 0 ? void 0 : actualMessage.action;
42425
- console.log("[ShadowSpace] \u68C0\u67E5\u54CD\u5E94: action=".concat(actualAction, ", messageId=").concat(actualMessageId, ", \u671F\u671B=").concat(messageId));
42765
+ // console.log(
42766
+ // `[ShadowSpace] 检查响应: action=${actualAction}, messageId=${actualMessageId}, 期望=${messageId}`
42767
+ // );
42426
42768
  if (actualMessageId === messageId &&
42427
42769
  actualAction === 'editor-state-response') {
42428
- console.log("[ShadowSpace] \u6536\u5230\u7F16\u8F91\u5668\u72B6\u6001\u54CD\u5E94");
42770
+ // console.log(`[ShadowSpace] 收到编辑器状态响应`);
42429
42771
  clearTimeout(timeout);
42430
42772
  if ((_a = actualMessage.message) === null || _a === void 0 ? void 0 : _a.success) {
42431
42773
  resolve(actualMessage.message.data);
@@ -42443,7 +42785,9 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42443
42785
  originalOnMessage(data);
42444
42786
  }
42445
42787
  };
42446
- console.log("[ShadowSpace] \u4E34\u65F6\u76D1\u542C\u5668\u5DF2\u8BBE\u7F6E\uFF0C\u53D1\u9001\u7F16\u8F91\u5668\u72B6\u6001\u8BF7\u6C42: ".concat(messageId));
42788
+ // console.log(
42789
+ // `[ShadowSpace] 临时监听器已设置,发送编辑器状态请求: ${messageId}`
42790
+ // );
42447
42791
  // 发送请求
42448
42792
  _this.socketStore.sendMessage({
42449
42793
  action: 'request-editor-state',
@@ -42454,7 +42798,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42454
42798
  });
42455
42799
  // 恢复原始处理器(在超时时间之后)
42456
42800
  setTimeout(function () {
42457
- console.log("[ShadowSpace] \u6062\u590D\u539F\u59CB\u76D1\u542C\u5668: ".concat(messageId));
42801
+ // console.log(`[ShadowSpace] 恢复原始监听器: ${messageId}`);
42458
42802
  _this.socketStore.onmsg = originalOnMessage;
42459
42803
  }, 31000);
42460
42804
  })];
@@ -42466,23 +42810,20 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42466
42810
  */
42467
42811
  ShadowSpaceCommandHandler.prototype.detectEditorChanges = function (spaceId, editorSnapshots) {
42468
42812
  return __awaiter(this, void 0, void 0, function () {
42469
- var safeEditorSnapshots, spaceSnapshots, snapshotCount, changes, summary, error_2;
42813
+ var safeEditorSnapshots, spaceSnapshots, changes, summary, error_2;
42470
42814
  return __generator(this, function (_a) {
42471
42815
  switch (_a.label) {
42472
42816
  case 0:
42473
42817
  _a.trys.push([0, 3, , 4]);
42474
- console.log('editorSnapshots: ', editorSnapshots);
42475
42818
  safeEditorSnapshots = Array.isArray(editorSnapshots)
42476
42819
  ? editorSnapshots
42477
42820
  : [];
42478
- console.log("[ShadowSpace] \u5F00\u59CB\u68C0\u6D4B\u53D8\u66F4: \u7A7A\u95F4=".concat(spaceId, ", \u7F16\u8F91\u5668\u6587\u4EF6=").concat(safeEditorSnapshots.length, "\u4E2A"));
42479
42821
  return [4 /*yield*/, this.shadowSpace.getSpaceSnapshots(spaceId)];
42480
42822
  case 1:
42481
42823
  spaceSnapshots = _a.sent();
42482
- snapshotCount = Array.isArray(spaceSnapshots)
42824
+ Array.isArray(spaceSnapshots)
42483
42825
  ? spaceSnapshots.length
42484
42826
  : 0;
42485
- console.log("[ShadowSpace] \u7A7A\u95F4\u5FEB\u7167: ".concat(snapshotCount, "\u4E2A\u6587\u4EF6"));
42486
42827
  return [4 /*yield*/, this.compareSnapshots(safeEditorSnapshots, spaceSnapshots)];
42487
42828
  case 2:
42488
42829
  changes = _a.sent();
@@ -42491,7 +42832,9 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42491
42832
  needPush: changes.filter(function (c) { return c.side === 'editor'; }).length,
42492
42833
  needPull: changes.filter(function (c) { return c.side === 'space'; }).length,
42493
42834
  };
42494
- console.log("[ShadowSpace] \u53D8\u66F4\u68C0\u6D4B\u5B8C\u6210: \u603B\u8BA1".concat(summary.total, "\u4E2A\u53D8\u66F4, \u9700\u63A8\u9001").concat(summary.needPush, "\u4E2A, \u9700\u62C9\u53D6").concat(summary.needPull, "\u4E2A"));
42835
+ // console.log(
42836
+ // `[ShadowSpace] 变更检测完成: 总计${summary.total}个变更, 需推送${summary.needPush}个, 需拉取${summary.needPull}个`
42837
+ // );
42495
42838
  return [2 /*return*/, {
42496
42839
  success: true,
42497
42840
  data: {
@@ -42518,10 +42861,11 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42518
42861
  * 比对编辑器和空间快照
42519
42862
  */
42520
42863
  ShadowSpaceCommandHandler.prototype.compareSnapshots = function (editorSnapshots, spaceSnapshots) {
42864
+ var _a, _b, _c;
42521
42865
  return __awaiter(this, void 0, void 0, function () {
42522
- var changes, safeEditorSnapshots, safeSpaceSnapshots, editorMap, spaceMap, editorMap_1, editorMap_1_1, _a, path, editorFile, spaceFile, spaceMap_1, spaceMap_1_1, _b, path, spaceFile, editorFile;
42523
- var e_2, _c, e_3, _d;
42524
- return __generator(this, function (_e) {
42866
+ var changes, safeEditorSnapshots, safeSpaceSnapshots, editorMap, spaceMap, editorMap_1, editorMap_1_1, _d, path, editorFile, spaceFile, spaceMap_1, spaceMap_1_1, _e, path, spaceFile, editorFile;
42867
+ var e_2, _f, e_3, _g;
42868
+ return __generator(this, function (_h) {
42525
42869
  changes = [];
42526
42870
  safeEditorSnapshots = Array.isArray(editorSnapshots)
42527
42871
  ? editorSnapshots
@@ -42534,7 +42878,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42534
42878
  try {
42535
42879
  // 检测编辑器的变更(新增、修改)
42536
42880
  for (editorMap_1 = __values(editorMap), editorMap_1_1 = editorMap_1.next(); !editorMap_1_1.done; editorMap_1_1 = editorMap_1.next()) {
42537
- _a = __read(editorMap_1_1.value, 2), path = _a[0], editorFile = _a[1];
42881
+ _d = __read(editorMap_1_1.value, 2), path = _d[0], editorFile = _d[1];
42538
42882
  spaceFile = spaceMap.get(path);
42539
42883
  if (!spaceFile) {
42540
42884
  // 编辑器新增的文件
@@ -42551,9 +42895,11 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42551
42895
  else if (editorFile.hash !== spaceFile.remoteHash) {
42552
42896
  // 编辑器修改的文件(基于云端哈希比对)
42553
42897
  console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u7F16\u8F91\u5668\u4FEE\u6539: ".concat(path), {
42554
- editorHash: editorFile.hash,
42555
- spaceRemoteHash: spaceFile.remoteHash,
42556
- spaceLocalHash: spaceFile.hash,
42898
+ editorHash: (_a = editorFile.hash) === null || _a === void 0 ? void 0 : _a.substring(0, 16),
42899
+ spaceRemoteHash: (_b = spaceFile.remoteHash) === null || _b === void 0 ? void 0 : _b.substring(0, 16),
42900
+ spaceLocalHash: (_c = spaceFile.hash) === null || _c === void 0 ? void 0 : _c.substring(0, 16),
42901
+ editorHashFull: editorFile.hash,
42902
+ spaceRemoteHashFull: spaceFile.remoteHash,
42557
42903
  });
42558
42904
  changes.push({
42559
42905
  action: 'modify',
@@ -42570,14 +42916,14 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42570
42916
  catch (e_2_1) { e_2 = { error: e_2_1 }; }
42571
42917
  finally {
42572
42918
  try {
42573
- if (editorMap_1_1 && !editorMap_1_1.done && (_c = editorMap_1.return)) _c.call(editorMap_1);
42919
+ if (editorMap_1_1 && !editorMap_1_1.done && (_f = editorMap_1.return)) _f.call(editorMap_1);
42574
42920
  }
42575
42921
  finally { if (e_2) throw e_2.error; }
42576
42922
  }
42577
42923
  try {
42578
42924
  // 检测空间的变更(删除、空间独有的修改)
42579
42925
  for (spaceMap_1 = __values(spaceMap), spaceMap_1_1 = spaceMap_1.next(); !spaceMap_1_1.done; spaceMap_1_1 = spaceMap_1.next()) {
42580
- _b = __read(spaceMap_1_1.value, 2), path = _b[0], spaceFile = _b[1];
42926
+ _e = __read(spaceMap_1_1.value, 2), path = _e[0], spaceFile = _e[1];
42581
42927
  editorFile = editorMap.get(path);
42582
42928
  if (!editorFile) {
42583
42929
  // 空间独有的文件(编辑器已删除)
@@ -42597,7 +42943,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42597
42943
  catch (e_3_1) { e_3 = { error: e_3_1 }; }
42598
42944
  finally {
42599
42945
  try {
42600
- if (spaceMap_1_1 && !spaceMap_1_1.done && (_d = spaceMap_1.return)) _d.call(spaceMap_1);
42946
+ if (spaceMap_1_1 && !spaceMap_1_1.done && (_g = spaceMap_1.return)) _g.call(spaceMap_1);
42601
42947
  }
42602
42948
  finally { if (e_3) throw e_3.error; }
42603
42949
  }
@@ -42605,12 +42951,132 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42605
42951
  });
42606
42952
  });
42607
42953
  };
42954
+ /**
42955
+ * 放弃本地变更
42956
+ * 将影子空间的状态更新为编辑器的版本,不再提示这些文件有变更
42957
+ */
42958
+ ShadowSpaceCommandHandler.prototype.discardChanges = function (filePaths) {
42959
+ return __awaiter(this, void 0, void 0, function () {
42960
+ var editorState, editorFiles;
42961
+ return __generator(this, function (_a) {
42962
+ switch (_a.label) {
42963
+ case 0:
42964
+ if (!filePaths || filePaths.length === 0) {
42965
+ throw new Error('No file paths provided');
42966
+ }
42967
+ console.log("[ShadowSpace] \u653E\u5F03\u53D8\u66F4: ".concat(filePaths.length, " \u4E2A\u6587\u4EF6"));
42968
+ return [4 /*yield*/, this.requestEditorState()];
42969
+ case 1:
42970
+ editorState = _a.sent();
42971
+ if (!editorState || !editorState.files) {
42972
+ throw new Error('Failed to get editor state');
42973
+ }
42974
+ editorFiles = editorState.files.filter(function (f) {
42975
+ return filePaths.includes(f.path);
42976
+ });
42977
+ console.log("[ShadowSpace] \u4ECE\u7F16\u8F91\u5668\u83B7\u53D6\u5230 ".concat(editorFiles.length, " \u4E2A\u6587\u4EF6"));
42978
+ if (editorFiles.length === 0) {
42979
+ throw new Error('No matching files found in editor');
42980
+ }
42981
+ // 同步到影子空间(覆盖本地变更)
42982
+ return [4 /*yield*/, this.shadowSpace.syncFromEditor(editorFiles)];
42983
+ case 2:
42984
+ // 同步到影子空间(覆盖本地变更)
42985
+ _a.sent();
42986
+ // 标记为远程修改,避免再次检测
42987
+ return [4 /*yield*/, this.shadowSpace.markAsRemoteModified(filePaths)];
42988
+ case 3:
42989
+ // 标记为远程修改,避免再次检测
42990
+ _a.sent();
42991
+ console.log("[ShadowSpace] \u6210\u529F\u653E\u5F03 ".concat(filePaths.length, " \u4E2A\u6587\u4EF6\u7684\u53D8\u66F4"));
42992
+ return [2 /*return*/, {
42993
+ message: 'Changes discarded successfully',
42994
+ fileCount: filePaths.length,
42995
+ discardedFiles: filePaths,
42996
+ timestamp: Date.now(),
42997
+ }];
42998
+ }
42999
+ });
43000
+ });
43001
+ };
42608
43002
  /**
42609
43003
  * 生成消息ID
42610
43004
  */
42611
43005
  ShadowSpaceCommandHandler.prototype.generateMessageId = function () {
42612
43006
  return "msg_".concat(Date.now(), "_").concat(Math.random().toString(36).substr(2, 9));
42613
43007
  };
43008
+ // ==================== 🆕 文件监听功能 ====================
43009
+ /**
43010
+ * 启动文件监听
43011
+ */
43012
+ ShadowSpaceCommandHandler.prototype.startFileWatching = function () {
43013
+ var _this = this;
43014
+ if (!this.currentUserId) {
43015
+ console.error('[ShadowSpace] 无法启动文件监听:用户ID未设置');
43016
+ return;
43017
+ }
43018
+ var spaceInfo = this.shadowSpace.getSpaceInfo();
43019
+ console.log('[ShadowSpace] 启动文件监听和变更聚合...');
43020
+ // 创建变更聚合器
43021
+ this.changeAggregator = new ChangeAggregator(spaceInfo.spaceId, spaceInfo.userId, function (event) { return _this.handleBatchChange(event); }, 500 // 500ms 防抖
43022
+ );
43023
+ // 添加变更监听器
43024
+ this.shadowSpace.addChangeListener(function (change) {
43025
+ if (_this.changeAggregator) {
43026
+ _this.changeAggregator.addChange(change);
43027
+ }
43028
+ });
43029
+ // 启动文件监听
43030
+ this.shadowSpace.startWatching();
43031
+ console.log('[ShadowSpace] 文件监听和变更聚合已启动');
43032
+ };
43033
+ /**
43034
+ * 停止文件监听
43035
+ */
43036
+ ShadowSpaceCommandHandler.prototype.stopFileWatching = function () {
43037
+ return __awaiter(this, void 0, void 0, function () {
43038
+ return __generator(this, function (_a) {
43039
+ switch (_a.label) {
43040
+ case 0:
43041
+ console.log('[ShadowSpace] 停止文件监听和变更聚合...');
43042
+ // 停止文件监听
43043
+ return [4 /*yield*/, this.shadowSpace.stopWatching()];
43044
+ case 1:
43045
+ // 停止文件监听
43046
+ _a.sent();
43047
+ // 销毁变更聚合器
43048
+ if (this.changeAggregator) {
43049
+ this.changeAggregator.destroy();
43050
+ this.changeAggregator = null;
43051
+ }
43052
+ console.log('[ShadowSpace] 文件监听和变更聚合已停止');
43053
+ return [2 /*return*/];
43054
+ }
43055
+ });
43056
+ });
43057
+ };
43058
+ /**
43059
+ * 处理批量变更
43060
+ */
43061
+ ShadowSpaceCommandHandler.prototype.handleBatchChange = function (event) {
43062
+ console.log("[ShadowSpace] \u63A8\u9001\u6279\u91CF\u53D8\u66F4\u4E8B\u4EF6: ".concat(event.changes.length, " \u4E2A\u6587\u4EF6"));
43063
+ // 推送批量变更事件到编辑器
43064
+ this.socketStore.sendMessage({
43065
+ action: 'shadow-space-batch-changed',
43066
+ message: {
43067
+ spaceId: event.spaceId,
43068
+ userId: event.userId,
43069
+ changes: event.changes,
43070
+ timestamp: event.timestamp,
43071
+ },
43072
+ });
43073
+ };
43074
+ /**
43075
+ * 获取监听状态
43076
+ */
43077
+ ShadowSpaceCommandHandler.prototype.isWatching = function () {
43078
+ return this.shadowSpace.isFileWatching();
43079
+ };
42614
43080
  return ShadowSpaceCommandHandler;
42615
43081
  }());
42616
43082
 
@@ -42750,11 +43216,31 @@ function startConnecting(options) {
42750
43216
  log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6587\u4EF6\u64CD\u4F5C\u5904\u7406\u5668\u5DF2\u521D\u59CB\u5316\uFF0C\u57FA\u7840\u76EE\u5F55: ").concat(fileOperationConfig.baseDir));
42751
43217
  shadowSpace_1 = null;
42752
43218
  shadowSpaceHandler_1 = null;
42753
- cleanup_1 = function () {
42754
- log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6B63\u5728\u6E05\u7406..."));
42755
- removePidFile();
42756
- process.exit(0);
42757
- };
43219
+ cleanup_1 = function () { return __awaiter(_this, void 0, void 0, function () {
43220
+ return __generator(this, function (_a) {
43221
+ switch (_a.label) {
43222
+ case 0:
43223
+ log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6B63\u5728\u6E05\u7406..."));
43224
+ if (!shadowSpaceHandler_1) return [3 /*break*/, 4];
43225
+ _a.label = 1;
43226
+ case 1:
43227
+ _a.trys.push([1, 3, , 4]);
43228
+ return [4 /*yield*/, shadowSpaceHandler_1.stopFileWatching()];
43229
+ case 2:
43230
+ _a.sent();
43231
+ log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6587\u4EF6\u76D1\u542C\u5DF2\u505C\u6B62"));
43232
+ return [3 /*break*/, 4];
43233
+ case 3:
43234
+ _a.sent();
43235
+ log("[\u8FDB\u7A0B ".concat(process.pid, "] \u505C\u6B62\u6587\u4EF6\u76D1\u542C\u5931\u8D25:"));
43236
+ return [3 /*break*/, 4];
43237
+ case 4:
43238
+ removePidFile();
43239
+ process.exit(0);
43240
+ return [2 /*return*/];
43241
+ }
43242
+ });
43243
+ }); };
42758
43244
  process.on('SIGINT', cleanup_1);
42759
43245
  process.on('SIGTERM', cleanup_1);
42760
43246
  process.on('uncaughtException', function (error) {
@@ -42786,6 +43272,9 @@ function startConnecting(options) {
42786
43272
  // 初始化影子空间指令处理器
42787
43273
  shadowSpaceHandler_1 = new ShadowSpaceCommandHandler(shadowSpace_1, currentSocket);
42788
43274
  shadowSpaceHandler_1.setCurrentUserId(account);
43275
+ // 🆕 启动文件监听
43276
+ shadowSpaceHandler_1.startFileWatching();
43277
+ log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6587\u4EF6\u76D1\u542C\u5DF2\u542F\u52A8"));
42789
43278
  return [3 /*break*/, 3];
42790
43279
  case 2:
42791
43280
  log("[\u8FDB\u7A0B ".concat(process.pid, "] \u8DF3\u8FC7\u5F71\u5B50\u7A7A\u95F4\u521D\u59CB\u5316\uFF08\u672A\u542F\u7528workspace\u6A21\u5F0F\uFF09"));
@@ -42811,13 +43300,11 @@ function startConnecting(options) {
42811
43300
  }, 5000);
42812
43301
  },
42813
43302
  onmsg: function (data) { return __awaiter(_this, void 0, void 0, function () {
42814
- var action, message, extracted, normalizedData, result, _a, error_2, error_3, userId, current, cwd, type, change, filePath;
43303
+ var action, message, extracted, normalizedData, result, _a, error_3, error_4, userId, current, cwd, type, change, filePath;
42815
43304
  var _b, _c;
42816
43305
  return __generator(this, function (_d) {
42817
43306
  switch (_d.label) {
42818
43307
  case 0:
42819
- // if (DEV_MODE) {
42820
- log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6536\u5230\u6D88\u606F: ").concat(JSON.stringify(data)));
42821
43308
  if (data === null || data === void 0 ? void 0 : data.action) {
42822
43309
  // 直接格式
42823
43310
  action = data.action;
@@ -42890,8 +43377,8 @@ function startConnecting(options) {
42890
43377
  log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u5DF2\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ").concat(message.message.path));
42891
43378
  return [3 /*break*/, 11];
42892
43379
  case 10:
42893
- error_2 = _d.sent();
42894
- log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25: ").concat(error_2));
43380
+ error_3 = _d.sent();
43381
+ log("[\u8FDB\u7A0B ".concat(process.pid, "] \u5F71\u5B50\u7A7A\u95F4\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25: ").concat(error_3));
42895
43382
  return [3 /*break*/, 11];
42896
43383
  case 11: return [3 /*break*/, 23];
42897
43384
  case 12: return [4 /*yield*/, fileHandler_1.readFile(message.path, message.encoding)];
@@ -42933,13 +43420,13 @@ function startConnecting(options) {
42933
43420
  });
42934
43421
  return [3 /*break*/, 25];
42935
43422
  case 24:
42936
- error_3 = _d.sent();
42937
- log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6587\u4EF6\u64CD\u4F5C\u9519\u8BEF: ").concat(error_3));
43423
+ error_4 = _d.sent();
43424
+ log("[\u8FDB\u7A0B ".concat(process.pid, "] \u6587\u4EF6\u64CD\u4F5C\u9519\u8BEF: ").concat(error_4));
42938
43425
  currentSocket === null || currentSocket === void 0 ? void 0 : currentSocket.sendMessage({
42939
43426
  action: "".concat(action, "-response"),
42940
43427
  message: {
42941
43428
  success: false,
42942
- error: error_3 instanceof Error ? error_3.message : String(error_3),
43429
+ error: error_4 instanceof Error ? error_4.message : String(error_4),
42943
43430
  },
42944
43431
  });
42945
43432
  return [3 /*break*/, 25];
@@ -48298,6 +48785,1155 @@ function cleanupOldLogs(logDir, debugDir) {
48298
48785
  });
48299
48786
  }
48300
48787
 
48788
+ /**
48789
+ * AI 工具配置
48790
+ */
48791
+ var AI_TOOLS = [
48792
+ {
48793
+ name: '🤖 Claude Code (Anthropic 官方)',
48794
+ value: 'claude-code',
48795
+ description: '支持 Hooks 和 TSX 检查器',
48796
+ },
48797
+ {
48798
+ name: '🎯 Cursor (AI-first IDE)',
48799
+ value: 'cursor',
48800
+ description: '支持 Rules 和自定义指令',
48801
+ },
48802
+ {
48803
+ name: '🌊 Windsurf (Codeium)',
48804
+ value: 'windsurf',
48805
+ description: '支持 Cascade 配置',
48806
+ },
48807
+ {
48808
+ name: '☁️ 阿里云 Coder',
48809
+ value: 'coder',
48810
+ description: '支持模板配置',
48811
+ },
48812
+ {
48813
+ name: '🔧 Augment (VSCode 插件)',
48814
+ value: 'augment',
48815
+ description: '支持上下文配置',
48816
+ },
48817
+ {
48818
+ name: '⏭️ 其他 / 跳过',
48819
+ value: 'other',
48820
+ description: '只生成基础配置',
48821
+ },
48822
+ ];
48823
+
48824
+ /**
48825
+ * 基础生成器 - 生成通用的 Space 配置文件
48826
+ */
48827
+ var BaseGenerator = /** @class */ (function () {
48828
+ function BaseGenerator(cwd, config, verbose) {
48829
+ this.cwd = cwd;
48830
+ this.config = config;
48831
+ this.verbose = verbose;
48832
+ }
48833
+ /**
48834
+ * 生成基础配置文件
48835
+ */
48836
+ BaseGenerator.prototype.generate = function (skipPrompts) {
48837
+ return __awaiter(this, void 0, void 0, function () {
48838
+ var files, appthenDir, configFile, gitignoreFile, promptFiles, error_1;
48839
+ return __generator(this, function (_a) {
48840
+ switch (_a.label) {
48841
+ case 0:
48842
+ files = [];
48843
+ _a.label = 1;
48844
+ case 1:
48845
+ _a.trys.push([1, 6, , 7]);
48846
+ appthenDir = path__namespace.join(this.cwd, '.appthen');
48847
+ this.ensureDirectory(appthenDir);
48848
+ return [4 /*yield*/, this.createSpaceConfig(appthenDir)];
48849
+ case 2:
48850
+ configFile = _a.sent();
48851
+ files.push(configFile);
48852
+ return [4 /*yield*/, this.createGitignore(appthenDir)];
48853
+ case 3:
48854
+ gitignoreFile = _a.sent();
48855
+ files.push(gitignoreFile);
48856
+ if (!!skipPrompts) return [3 /*break*/, 5];
48857
+ return [4 /*yield*/, this.createPrompts(appthenDir)];
48858
+ case 4:
48859
+ promptFiles = _a.sent();
48860
+ files.push.apply(files, __spreadArray([], __read(promptFiles), false));
48861
+ _a.label = 5;
48862
+ case 5: return [2 /*return*/, {
48863
+ success: true,
48864
+ files: files,
48865
+ message: 'Base configuration created successfully',
48866
+ }];
48867
+ case 6:
48868
+ error_1 = _a.sent();
48869
+ return [2 /*return*/, {
48870
+ success: false,
48871
+ files: [],
48872
+ error: error_1.message,
48873
+ }];
48874
+ case 7: return [2 /*return*/];
48875
+ }
48876
+ });
48877
+ });
48878
+ };
48879
+ /**
48880
+ * 确保目录存在
48881
+ */
48882
+ BaseGenerator.prototype.ensureDirectory = function (dir) {
48883
+ if (!fs__namespace.existsSync(dir)) {
48884
+ fs__namespace.mkdirSync(dir, { recursive: true });
48885
+ if (this.verbose) {
48886
+ console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(dir));
48887
+ }
48888
+ }
48889
+ };
48890
+ /**
48891
+ * 创建 space-config.json
48892
+ */
48893
+ BaseGenerator.prototype.createSpaceConfig = function (appthenDir) {
48894
+ return __awaiter(this, void 0, void 0, function () {
48895
+ var configPath, configContent;
48896
+ return __generator(this, function (_a) {
48897
+ configPath = path__namespace.join(appthenDir, 'space-config.json');
48898
+ configContent = __assign(__assign({}, this.config), {
48899
+ // 添加一些额外的配置
48900
+ settings: {
48901
+ autoSync: true,
48902
+ watchPatterns: ['src/**/*', 'docs/**/*'],
48903
+ ignorePatterns: [
48904
+ 'node_modules/**',
48905
+ 'dist/**',
48906
+ 'build/**',
48907
+ '.git/**',
48908
+ '*.log',
48909
+ ],
48910
+ } });
48911
+ fs__namespace.writeFileSync(configPath, JSON.stringify(configContent, null, 2));
48912
+ if (this.verbose) {
48913
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
48914
+ }
48915
+ return [2 /*return*/, configPath];
48916
+ });
48917
+ });
48918
+ };
48919
+ /**
48920
+ * 创建 .gitignore
48921
+ */
48922
+ BaseGenerator.prototype.createGitignore = function (appthenDir) {
48923
+ return __awaiter(this, void 0, void 0, function () {
48924
+ var gitignorePath, gitignoreContent;
48925
+ return __generator(this, function (_a) {
48926
+ gitignorePath = path__namespace.join(appthenDir, '.gitignore');
48927
+ gitignoreContent = "# Shadow Space \u6587\u4EF6\nshadow-space-*.json\n\n# \u65E5\u5FD7\u6587\u4EF6\n*.log\n\n# \u4E34\u65F6\u6587\u4EF6\n*.tmp\n.DS_Store\n\n# \u7F16\u8F91\u5668\u914D\u7F6E\uFF08\u53EF\u9009\uFF09\n# .vscode/\n# .idea/\n";
48928
+ fs__namespace.writeFileSync(gitignorePath, gitignoreContent);
48929
+ if (this.verbose) {
48930
+ console.log("\uD83D\uDCDD \u521B\u5EFA .gitignore: ".concat(gitignorePath));
48931
+ }
48932
+ return [2 /*return*/, gitignorePath];
48933
+ });
48934
+ });
48935
+ };
48936
+ /**
48937
+ * 创建提示词目录和文件
48938
+ */
48939
+ BaseGenerator.prototype.createPrompts = function (appthenDir) {
48940
+ return __awaiter(this, void 0, void 0, function () {
48941
+ var files, promptsDir, readmeFile, templateFiles;
48942
+ return __generator(this, function (_a) {
48943
+ switch (_a.label) {
48944
+ case 0:
48945
+ files = [];
48946
+ promptsDir = path__namespace.join(appthenDir, 'prompts');
48947
+ this.ensureDirectory(promptsDir);
48948
+ return [4 /*yield*/, this.createPromptsReadme(promptsDir)];
48949
+ case 1:
48950
+ readmeFile = _a.sent();
48951
+ files.push(readmeFile);
48952
+ return [4 /*yield*/, this.copyTemplateFiles(promptsDir)];
48953
+ case 2:
48954
+ templateFiles = _a.sent();
48955
+ files.push.apply(files, __spreadArray([], __read(templateFiles), false));
48956
+ return [2 /*return*/, files];
48957
+ }
48958
+ });
48959
+ });
48960
+ };
48961
+ /**
48962
+ * 创建提示词 README
48963
+ */
48964
+ BaseGenerator.prototype.createPromptsReadme = function (promptsDir) {
48965
+ return __awaiter(this, void 0, void 0, function () {
48966
+ var readmePath, readmeContent;
48967
+ return __generator(this, function (_a) {
48968
+ readmePath = path__namespace.join(promptsDir, 'README.md');
48969
+ readmeContent = "# Agent+ Space \u63D0\u793A\u8BCD\n\n\u8FD9\u4E2A\u76EE\u5F55\u5305\u542B\u4E86\u7528\u4E8E AI \u7F16\u7801\u5DE5\u5177\u7684\u63D0\u793A\u8BCD\u6A21\u677F\uFF0C\u5E2E\u52A9 AI \u7406\u89E3\u9879\u76EE\u89C4\u8303\u5E76\u751F\u6210\u7B26\u5408\u8981\u6C42\u7684\u4EE3\u7801\u3002\n\n## \uD83D\uDCDA \u63D0\u793A\u8BCD\u6587\u4EF6\u8BF4\u660E\n\n### \u6838\u5FC3\u6587\u6863\n\n1. **project-guide.md** - \u9879\u76EE\u5F00\u53D1\u603B\u6307\u5357 \u2B50\n - \u9879\u76EE\u6982\u8FF0\u548C\u7ED3\u6784\n - \u5F00\u53D1\u89C4\u8303\u548C\u6D41\u7A0B\n - \u5FEB\u901F\u5F00\u59CB\u6307\u5357\n - \u6700\u4F73\u5B9E\u8DF5\n\n2. **tsx-generation.md** - TSX \u4EE3\u7801\u751F\u6210\u89C4\u8303 \u2B50\u2B50\u2B50\n - \u5B8C\u6574\u7684\u6587\u4EF6\u7ED3\u6784\u8981\u6C42\n - \u4E25\u683C\u7684 render() \u65B9\u6CD5\u7EA6\u675F\n - TypeScript \u8BED\u6CD5\u9650\u5236\n - JSX \u4F4D\u7F6E\u9650\u5236\n - \u5B8C\u6574\u793A\u4F8B\u4EE3\u7801\n - \u5E38\u89C1\u9519\u8BEF\u548C\u4FEE\u590D\n\n3. **decision-tree.md** - AI \u51B3\u7B56\u6811 \u2B50\u2B50\n - \u5E2E\u52A9 AI \u505A\u51FA\u6B63\u786E\u51B3\u7B56\n - \u5173\u952E\u51B3\u7B56\u70B9\u8BF4\u660E\n - \u5E38\u89C1\u9519\u8BEF\u51B3\u7B56\u5206\u6790\n - \u62D2\u7EDD\u751F\u6210\u7684\u6807\u51C6\u54CD\u5E94\n\n4. **validation-checklist.md** - \u9A8C\u8BC1\u6E05\u5355 \u2B50\u2B50\n - \u8BE6\u7EC6\u7684\u9A8C\u8BC1\u6D41\u7A0B\n - 8 \u4E2A\u9636\u6BB5\u7684\u68C0\u67E5\u9879\n - \u5E38\u89C1\u9519\u8BEF\u68C0\u67E5\n - \u9A8C\u8BC1\u5DE5\u5177\u4F7F\u7528\n\n5. **code-review.md** - \u4EE3\u7801\u5BA1\u67E5\u6307\u5357\n - \u5BA1\u67E5\u68C0\u67E5\u6E05\u5355\n - \u5E38\u89C1\u95EE\u9898\u8BC6\u522B\n - \u53CD\u9988\u6A21\u677F\n\n6. **refactoring.md** - \u91CD\u6784\u6307\u5357\n - \u91CD\u6784\u539F\u5219\n - \u5E38\u89C1\u91CD\u6784\u6A21\u5F0F\n - \u6027\u80FD\u4F18\u5316\u6280\u5DE7\n\n## \uD83D\uDE80 \u4F7F\u7528\u65B9\u6CD5\n\n### \u5BF9\u4E8E\u5F00\u53D1\u8005\n\n1. **\u9996\u6B21\u5F00\u53D1\u524D**\uFF1A\u9605\u8BFB `project-guide.md` \u4E86\u89E3\u9879\u76EE\u6982\u51B5\n2. **\u7F16\u5199 TSX \u4EE3\u7801\u524D**\uFF1A\u8BE6\u7EC6\u9605\u8BFB `tsx-generation.md`\n3. **\u4EE3\u7801\u9A8C\u8BC1**\uFF1A\u4F7F\u7528 `validation-checklist.md` \u8FDB\u884C\u81EA\u67E5\n4. **\u4EE3\u7801\u5BA1\u67E5**\uFF1A\u53C2\u8003 `code-review.md` \u8FDB\u884C\u5BA1\u67E5\n\n### \u5BF9\u4E8E AI \u5DE5\u5177\n\n\u6839\u636E\u4F60\u4F7F\u7528\u7684 AI \u5DE5\u5177\uFF0C\u5C06\u63D0\u793A\u8BCD\u6DFB\u52A0\u5230\u5BF9\u5E94\u7684\u914D\u7F6E\u4E2D\uFF1A\n\n#### Claude Code\n\u5728\u5BF9\u8BDD\u4E2D\u76F4\u63A5\u5F15\u7528\u8FD9\u4E9B\u63D0\u793A\u8BCD\uFF0C\u6216\u8005\u6DFB\u52A0\u5230\u9879\u76EE\u7684 `.claude/` \u914D\u7F6E\u4E2D\u3002\n\n#### Cursor\n\u5C06\u63D0\u793A\u8BCD\u5185\u5BB9\u6DFB\u52A0\u5230 `.cursor/rules.md` \u6587\u4EF6\u4E2D\u3002\n\n#### Windsurf\n\u5C06\u63D0\u793A\u8BCD\u6DFB\u52A0\u5230 Cascade \u914D\u7F6E\u4E2D\u3002\n\n#### \u963F\u91CC\u4E91 Coder\n\u5728 Coder \u7684\u8BBE\u7F6E\u4E2D\u6DFB\u52A0\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u3002\n\n#### Augment\n\u5C06\u63D0\u793A\u8BCD\u6DFB\u52A0\u5230 `.augment/context/` \u76EE\u5F55\u4E2D\u3002\n\n## \u26A0\uFE0F \u91CD\u8981\u63D0\u793A\n\n### TSX \u4EE3\u7801\u5FC5\u987B\u7B26\u5408\u89C4\u8303\n- \u4E0D\u7B26\u5408\u89C4\u8303\u7684\u4EE3\u7801\u65E0\u6CD5\u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\n- \u5FC5\u987B\u4F7F\u7528 `appthen check-tsx` \u8FDB\u884C\u9A8C\u8BC1\n- \u7981\u6B62\u4F7F\u7528\u6807\u51C6\u7684 lint/format \u5DE5\u5177\n\n### AI \u5DE5\u5177\u914D\u7F6E\n- \u5C06\u8FD9\u4E9B\u63D0\u793A\u8BCD\u6587\u4EF6\u6DFB\u52A0\u5230 AI \u5DE5\u5177\u7684\u4E0A\u4E0B\u6587\u4E2D\n- \u786E\u4FDD AI \u7406\u89E3\u5E76\u9075\u5B88\u6240\u6709\u7EA6\u675F\n- \u5F53\u4E0D\u786E\u5B9A\u65F6\uFF0CAI \u5E94\u8BE5\u62D2\u7EDD\u751F\u6210\u800C\u4E0D\u662F\u5192\u9669\n\n## \uD83D\uDEE0\uFE0F \u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\n\n\u4F60\u53EF\u4EE5\u6839\u636E\u9879\u76EE\u9700\u6C42\u6DFB\u52A0\u81EA\u5B9A\u4E49\u63D0\u793A\u8BCD\u6587\u4EF6\uFF1A\n\n- `api-design.md`: API \u8BBE\u8BA1\u89C4\u8303\n- `testing.md`: \u6D4B\u8BD5\u7F16\u5199\u6307\u5357\n- `styling.md`: \u6837\u5F0F\u7F16\u5199\u89C4\u8303\n- `performance.md`: \u6027\u80FD\u4F18\u5316\u6307\u5357\n- `backend-guide.md`: \u540E\u7AEF\u5F00\u53D1\u6307\u5357\uFF08midwayjs\uFF09\n\n## \uD83D\uDD04 \u66F4\u65B0\u63D0\u793A\u8BCD\n\n\u63D0\u793A\u8BCD\u4F1A\u968F\u7740\u9879\u76EE\u89C4\u8303\u7684\u6F14\u8FDB\u800C\u66F4\u65B0\uFF1A\n- \u5B9A\u671F\u68C0\u67E5\u5E76\u66F4\u65B0\u8FD9\u4E9B\u6587\u4EF6\n- \u6839\u636E\u5B9E\u9645\u95EE\u9898\u8865\u5145\u65B0\u7684\u89C4\u5219\n- \u8BB0\u5F55\u5E38\u89C1\u9519\u8BEF\u548C\u89E3\u51B3\u65B9\u6848\n\n## \uD83D\uDCAC \u53CD\u9988\u548C\u6539\u8FDB\n\n\u5982\u679C\u4F60\u53D1\u73B0\u63D0\u793A\u8BCD\u6709\u95EE\u9898\u6216\u6709\u6539\u8FDB\u5EFA\u8BAE\uFF1A\n- \u5728\u9879\u76EE\u4E2D\u521B\u5EFA Issue\n- \u76F4\u63A5\u4FEE\u6539\u63D0\u793A\u8BCD\u6587\u4EF6\u5E76\u63D0\u4EA4 PR\n- \u4E0E\u56E2\u961F\u5206\u4EAB\u4F60\u7684\u7ECF\u9A8C\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u9075\u5B88\u89C4\u8303\u662F\u6210\u529F\u7684\u5173\u952E\uFF01** \uD83C\uDFAF\n";
48970
+ fs__namespace.writeFileSync(readmePath, readmeContent);
48971
+ if (this.verbose) {
48972
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u63D0\u793A\u8BCD README: ".concat(readmePath));
48973
+ }
48974
+ return [2 /*return*/, readmePath];
48975
+ });
48976
+ });
48977
+ };
48978
+ /**
48979
+ * 复制模板文件到提示词目录
48980
+ */
48981
+ BaseGenerator.prototype.copyTemplateFiles = function (promptsDir) {
48982
+ return __awaiter(this, void 0, void 0, function () {
48983
+ var files, projectGuidePath, projectGuideContent, tsxGenerationPath, tsxGenerationContent, decisionTreePath, decisionTreeContent, validationPath, validationContent, codeReviewPath, codeReviewContent, refactoringPath, refactoringContent;
48984
+ return __generator(this, function (_a) {
48985
+ files = [];
48986
+ projectGuidePath = path__namespace.join(promptsDir, 'project-guide.md');
48987
+ projectGuideContent = this.getProjectGuideTemplate();
48988
+ fs__namespace.writeFileSync(projectGuidePath, projectGuideContent);
48989
+ files.push(projectGuidePath);
48990
+ if (this.verbose) {
48991
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: project-guide.md");
48992
+ }
48993
+ tsxGenerationPath = path__namespace.join(promptsDir, 'tsx-generation.md');
48994
+ tsxGenerationContent = this.getTsxGenerationTemplate();
48995
+ fs__namespace.writeFileSync(tsxGenerationPath, tsxGenerationContent);
48996
+ files.push(tsxGenerationPath);
48997
+ if (this.verbose) {
48998
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: tsx-generation.md");
48999
+ }
49000
+ decisionTreePath = path__namespace.join(promptsDir, 'decision-tree.md');
49001
+ decisionTreeContent = this.getDecisionTreeTemplate();
49002
+ fs__namespace.writeFileSync(decisionTreePath, decisionTreeContent);
49003
+ files.push(decisionTreePath);
49004
+ if (this.verbose) {
49005
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: decision-tree.md");
49006
+ }
49007
+ validationPath = path__namespace.join(promptsDir, 'validation-checklist.md');
49008
+ validationContent = this.getValidationChecklistTemplate();
49009
+ fs__namespace.writeFileSync(validationPath, validationContent);
49010
+ files.push(validationPath);
49011
+ if (this.verbose) {
49012
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: validation-checklist.md");
49013
+ }
49014
+ codeReviewPath = path__namespace.join(promptsDir, 'code-review.md');
49015
+ codeReviewContent = this.getCodeReviewTemplate();
49016
+ fs__namespace.writeFileSync(codeReviewPath, codeReviewContent);
49017
+ files.push(codeReviewPath);
49018
+ if (this.verbose) {
49019
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: code-review.md");
49020
+ }
49021
+ refactoringPath = path__namespace.join(promptsDir, 'refactoring.md');
49022
+ refactoringContent = this.getRefactoringTemplate();
49023
+ fs__namespace.writeFileSync(refactoringPath, refactoringContent);
49024
+ files.push(refactoringPath);
49025
+ if (this.verbose) {
49026
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u6A21\u677F\u6587\u4EF6: refactoring.md");
49027
+ }
49028
+ return [2 /*return*/, files];
49029
+ });
49030
+ });
49031
+ };
49032
+ /**
49033
+ * 获取项目开发总指南模板内容
49034
+ */
49035
+ BaseGenerator.prototype.getProjectGuideTemplate = function () {
49036
+ return "# Appthen \u9879\u76EE\u5F00\u53D1\u89C4\u8303\n\n## \uD83D\uDCCB \u9879\u76EE\u6982\u8FF0\n\n\u672C\u9879\u76EE\u662F **Appthen \u4F4E\u4EE3\u7801\u5E73\u53F0**\uFF0C\u652F\u6301\u7528\u9AD8\u4EE3\u7801\u5F00\u53D1\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u7684 React \u9875\u9762\u548C\u7EC4\u4EF6\u3002\n\n### \u9879\u76EE\u7ED3\u6784\n\n- **app/** - \u524D\u7AEF\u4EE3\u7801\uFF08\u540C\u6B65\u81EA\u4F4E\u4EE3\u7801\u4EA7\u54C1 Appthen\uFF09\n - \u4F7F\u7528\u7279\u6B8A\u89C4\u8303\u7684 TSX \u5B9E\u73B0 React \u9875\u9762\u548C\u7EC4\u4EF6\n - \u4EE3\u7801\u4F1A\u88AB\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u89E3\u6790\u548C\u5BFC\u5165\n- **server/** - \u540E\u7AEF\u4EE3\u7801\uFF08\u57FA\u4E8E cool-admin \u548C midwayjs\uFF09\n - \u4F7F\u7528 midwayjs \u6846\u67B6\u5F00\u53D1\u540E\u7AEF\u670D\u52A1\n - \u63D0\u4F9B\u63A5\u53E3\u3001\u6570\u636E\u5B57\u6BB5\u3001\u4E1A\u52A1\u6D41\u7A0B\u7B49\u4FE1\u606F\n\n---\n\n## \uD83D\uDEA8 \u91CD\u8981\uFF1A\u5F00\u53D1\u524D\u5FC5\u8BFB\n\n### \u524D\u7AEF\u5F00\u53D1\u89C4\u8303\n\n**[\u5173\u952E] \u5F00\u53D1 React \u9875\u9762\u548C\u7EC4\u4EF6\uFF08TSX \u6587\u4EF6\uFF09\u65F6\uFF1A**\n\n1. **\u5FC5\u987B\u5148\u9605\u8BFB** `.appthen/prompts/tsx-generation.md`\n - \u4E86\u89E3\u7279\u6B8A\u7684 TSX \u8BED\u6CD5\u89C4\u8303\n - \u4E25\u683C\u9075\u5B88\u975E\u5E38\u89C4\u7684 TSX/JSX \u8BED\u6CD5\u8981\u6C42\n\n2. **\u5FC5\u987B\u8FDB\u884C\u9A8C\u8BC1**\n - \u8BFB\u5199 TSX \u6587\u4EF6\u540E\uFF0C\u8C03\u7528\u547D\u4EE4\u9A8C\u8BC1\u8BED\u6CD5\uFF1A\n ```bash\n appthen check-tsx -f \"app/src/pages/YourPage.tsx\"\n ```\n - \u5982\u4E0D\u7B26\u5408\u89C4\u8303\uFF0C\u6839\u636E\u9A8C\u8BC1\u7ED3\u679C\u8FDB\u884C\u4FEE\u6B63\n\n3. **\u7981\u6B62\u4F7F\u7528\u6807\u51C6\u5DE5\u5177**\n - \u274C \u4E0D\u8981\u8FD0\u884C `eslint`\u3001`prettier`\u3001`tsc` \u7B49\u6807\u51C6\u5DE5\u5177\n - \u274C \u8FD9\u4E9B\u5DE5\u5177\u4F1A\u7834\u574F\u6211\u4EEC\u7684\u7279\u6B8A TSX \u8BED\u6CD5\n - \u2705 \u53EA\u4F7F\u7528 `appthen check-tsx` \u8FDB\u884C\u9A8C\u8BC1\n\n---\n\n## \uD83C\uDFAF \u4E1A\u52A1\u5F00\u53D1\u6D41\u7A0B\n\n### 1. \u83B7\u53D6\u63A5\u53E3\u4FE1\u606F\n\n\u4ECE server \u7AEF\u83B7\u53D6\u63A5\u53E3\u5BF9\u63A5\u6240\u9700\u7684\u76F8\u5173\u4FE1\u606F\uFF1A\n- \u63A5\u53E3\u5730\u5740\u548C\u53C2\u6570\n- \u6570\u636E\u5B57\u6BB5\u5B9A\u4E49\n- \u4E1A\u52A1\u6D41\u7A0B\u8BF4\u660E\n\n### 2. \u5F00\u53D1\u524D\u7AEF\u754C\u9762\n\n\u6839\u636E\u63A5\u53E3\u4FE1\u606F\u5F00\u53D1\u524D\u7AEF\u754C\u9762\uFF1A\n- \u4F7F\u7528 TSX \u7279\u6B8A\u8BED\u6CD5\n- \u9075\u5B88\u4E25\u683C\u7684 render() \u65B9\u6CD5\u7EA6\u675F\n- \u4F7F\u7528 @DataSource \u88C5\u9970\u5668\u5BF9\u63A5\u63A5\u53E3\n\n### 3. \u9A8C\u8BC1\u548C\u6D4B\u8BD5\n\n- \u4F7F\u7528 `appthen check-tsx` \u9A8C\u8BC1\u8BED\u6CD5\n- \u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\u6D4B\u8BD5\n- \u786E\u4FDD\u529F\u80FD\u6B63\u5E38\n\n---\n\n## \uD83D\uDCDA \u76F8\u5173\u6587\u6863\n\n- **tsx-generation.md** - TSX \u4EE3\u7801\u751F\u6210\u5B8C\u6574\u89C4\u8303\n- **decision-tree.md** - AI \u51B3\u7B56\u6811\uFF08\u5E2E\u52A9 AI \u505A\u51FA\u6B63\u786E\u51B3\u7B56\uFF09\n- **validation-checklist.md** - \u4EE3\u7801\u9A8C\u8BC1\u6E05\u5355\n- **code-review.md** - \u4EE3\u7801\u5BA1\u67E5\u6307\u5357\n- **refactoring.md** - \u4EE3\u7801\u91CD\u6784\u6307\u5357\n\n---\n\n## \u26A0\uFE0F \u7279\u522B\u6CE8\u610F\n\n### TSX \u8BED\u6CD5\u7684\u7279\u6B8A\u6027\n\n\u6211\u4EEC\u7684 TSX \u8BED\u6CD5\u4E0E\u6807\u51C6 React/TypeScript \u4E0D\u540C\uFF1A\n\n1. **render() \u65B9\u6CD5\u7EA6\u675F**\n - \u4E0D\u80FD\u6709\u4EFB\u4F55\u53D8\u91CF\u58F0\u660E\n - \u4E0D\u80FD\u6709\u4EFB\u4F55\u903B\u8F91\u8BED\u53E5\n - \u53EA\u80FD\u76F4\u63A5\u8BBF\u95EE this.state \u548C this.props\n\n2. **TypeScript \u8BED\u6CD5\u9650\u5236**\n - \u65B9\u6CD5\u4E0D\u80FD\u6709\u7C7B\u578B\u6CE8\u89E3\n - \u53EA\u5728 IProps/IState \u4E2D\u4F7F\u7528\u7C7B\u578B\n - \u4E0D\u80FD\u4F7F\u7528\u6CDB\u578B\uFF08\u9664\u4E86 React.Component\uFF09\n\n3. **JSX \u4F4D\u7F6E\u9650\u5236**\n - \u53EA\u6709 render() \u65B9\u6CD5\u53EF\u4EE5\u5305\u542B JSX\n - \u5176\u4ED6\u65B9\u6CD5\u548C\u5C5E\u6027\u4E0D\u80FD\u6709 JSX\n\n### \u4E3A\u4EC0\u4E48\u6709\u8FD9\u4E9B\u9650\u5236\uFF1F\n\n\u8FD9\u4E9B\u9650\u5236\u662F\u4E3A\u4E86\u8BA9\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u80FD\u591F\uFF1A\n- \u89E3\u6790\u548C\u7406\u89E3\u4EE3\u7801\u7ED3\u6784\n- \u63D0\u53D6\u6570\u636E\u6A21\u578B\u548C\u63A5\u53E3\u5B9A\u4E49\n- \u5728\u53EF\u89C6\u5316\u7F16\u8F91\u5668\u4E2D\u7F16\u8F91\n- \u751F\u6210\u7B26\u5408\u89C4\u8303\u7684\u4EE3\u7801\n\n**\u8FDD\u53CD\u89C4\u8303 = \u65E0\u6CD5\u5BFC\u5165\u4F4E\u4EE3\u7801\u7CFB\u7EDF\uFF01**\n\n---\n\n## \uD83D\uDE80 \u5FEB\u901F\u5F00\u59CB\n\n### \u521B\u5EFA\u65B0\u9875\u9762\n\n```bash\n# 1. \u67E5\u770B TSX \u751F\u6210\u89C4\u8303\ncat .appthen/prompts/tsx-generation.md\n\n# 2. \u521B\u5EFA\u9875\u9762\u6587\u4EF6\n# \u4F7F\u7528 AI \u5DE5\u5177\u751F\u6210\uFF0C\u786E\u4FDD\u9075\u5B88\u89C4\u8303\n\n# 3. \u9A8C\u8BC1\u8BED\u6CD5\nappthen check-tsx -f \"app/src/pages/NewPage.tsx\"\n\n# 4. \u4FEE\u6B63\u9519\u8BEF\uFF08\u5982\u679C\u6709\uFF09\n# \u6839\u636E\u9A8C\u8BC1\u7ED3\u679C\u4FEE\u6B63\u4EE3\u7801\n\n# 5. \u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\u6D4B\u8BD5\n```\n\n### \u4FEE\u6539\u73B0\u6709\u9875\u9762\n\n```bash\n# 1. \u67E5\u770B\u73B0\u6709\u4EE3\u7801\ncat app/src/pages/ExistingPage.tsx\n\n# 2. \u4FEE\u6539\u4EE3\u7801\uFF08\u9075\u5B88\u89C4\u8303\uFF09\n\n# 3. \u9A8C\u8BC1\u8BED\u6CD5\nappthen check-tsx -f \"app/src/pages/ExistingPage.tsx\"\n\n# 4. \u6D4B\u8BD5\u529F\u80FD\n```\n\n---\n\n## \uD83D\uDCA1 \u6700\u4F73\u5B9E\u8DF5\n\n1. **\u59CB\u7EC8\u5148\u9605\u8BFB\u89C4\u8303** - \u4E0D\u8981\u51ED\u7ECF\u9A8C\u5199\u4EE3\u7801\n2. **\u9891\u7E41\u9A8C\u8BC1** - \u6BCF\u6B21\u4FEE\u6539\u540E\u90FD\u8FD0\u884C check-tsx\n3. **\u53C2\u8003\u793A\u4F8B** - \u67E5\u770B\u73B0\u6709\u9875\u9762\u7684\u5B9E\u73B0\u65B9\u5F0F\n4. **\u4F7F\u7528 AI \u8F85\u52A9** - \u8BA9 AI \u9075\u5B88\u89C4\u8303\u751F\u6210\u4EE3\u7801\n5. **\u6D4B\u8BD5\u5BFC\u5165** - \u786E\u4FDD\u80FD\u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u6B63\u5E38\u5BFC\u5165\n\n---\n\n## \uD83C\uDD98 \u9047\u5230\u95EE\u9898\uFF1F\n\n1. **\u8BED\u6CD5\u9A8C\u8BC1\u5931\u8D25** \u2192 \u67E5\u770B validation-checklist.md\n2. **\u4E0D\u77E5\u9053\u5982\u4F55\u5B9E\u73B0** \u2192 \u67E5\u770B tsx-generation.md \u4E2D\u7684\u793A\u4F8B\n3. **AI \u751F\u6210\u9519\u8BEF\u4EE3\u7801** \u2192 \u67E5\u770B decision-tree.md \u4E86\u89E3 AI \u51B3\u7B56\u6D41\u7A0B\n4. **\u9700\u8981\u91CD\u6784\u4EE3\u7801** \u2192 \u67E5\u770B refactoring.md\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u9075\u5B88\u89C4\u8303\u662F\u6210\u529F\u7684\u5173\u952E\uFF01** \uD83C\uDFAF\n";
49037
+ };
49038
+ /**
49039
+ * 获取 TSX 生成模板内容
49040
+ */
49041
+ BaseGenerator.prototype.getTsxGenerationTemplate = function () {
49042
+ return "# TSX \u4EE3\u7801\u751F\u6210\u89C4\u8303\n\n\u751F\u6210\u7B26\u5408\u5E73\u53F0\u89C4\u8303\u7684 TSX \u4EE3\u7801\u65F6\uFF0C\u8BF7\u9075\u5FAA\u4EE5\u4E0B\u89C4\u5219\uFF1A\n\n## 1. \u6587\u4EF6\u7ED3\u6784\n\n```typescript\n/**\n * @type Page|Component\n * @description \u7EC4\u4EF6\u63CF\u8FF0\n */\n\nimport React from 'react';\n\nclass IProps {\n // Props \u5B9A\u4E49\n}\n\nclass IState {\n // State \u5B9A\u4E49\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n return (\n // JSX\n );\n }\n}\n\nexport default Document;\n```\n\n## 2. \u5173\u952E\u89C4\u5219\n\n- \u2705 \u5FC5\u987B\u5305\u542B JSDoc \u5143\u6570\u636E\u6CE8\u91CA\n- \u2705 \u4F7F\u7528 class IProps \u548C class IState\n- \u2705 render() \u65B9\u6CD5\u53EA\u5305\u542B return \u8BED\u53E5\n- \u2705 \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u8FDB\u884C\u6761\u4EF6\u6E32\u67D3\n- \u274C \u907F\u514D\u5728 render() \u4E2D\u4F7F\u7528\u4E09\u5143\u8868\u8FBE\u5F0F\n- \u274C \u907F\u514D\u5728\u65B9\u6CD5\u4E2D\u4F7F\u7528 TypeScript \u7C7B\u578B\u6CE8\u89E3\n\n\u8BE6\u7EC6\u89C4\u8303\u8BF7\u53C2\u8003\u9879\u76EE\u6587\u6863\u3002\n";
49043
+ };
49044
+ /**
49045
+ * 获取决策树模板内容
49046
+ */
49047
+ BaseGenerator.prototype.getDecisionTreeTemplate = function () {
49048
+ return "# AI \u51B3\u7B56\u6811 - TSX \u4EE3\u7801\u751F\u6210\u51B3\u7B56\u6307\u5357\n\n## \uD83C\uDFAF \u76EE\u7684\n\n\u5E2E\u52A9 AI \u5728\u751F\u6210 TSX \u4EE3\u7801\u65F6\u505A\u51FA\u6B63\u786E\u7684\u51B3\u7B56\uFF0C\u907F\u514D\u5E38\u89C1\u9519\u8BEF\u3002\n\n---\n\n## \uD83D\uDCCA \u51B3\u7B56\u6D41\u7A0B\u56FE\n\n```\n\u7528\u6237\u8BF7\u6C42\n \u2193\n\u662F\u5426\u6D89\u53CA TSX \u6587\u4EF6\uFF1F\n \u251C\u2500 \u5426 \u2192 \u6B63\u5E38\u5904\u7406\n \u2514\u2500 \u662F \u2192 \u8FDB\u5165 TSX \u51B3\u7B56\u6D41\u7A0B\n \u2193\n \u662F\u5426\u662F\"\u521B\u5EFA\u9875\u9762/\u7EC4\u4EF6\"\uFF1F\n \u251C\u2500 \u662F \u2192 [\u9AD8\u5EA6\u8B66\u6212] \u8FDB\u5165\u9875\u9762/\u7EC4\u4EF6\u751F\u6210\u6D41\u7A0B\n \u2502 \u2193\n \u2502 \u6267\u884C\u9884\u751F\u6210\u9A8C\u8BC1\u6E05\u5355\n \u2502 \u2193\n \u2502 \u6240\u6709\u68C0\u67E5\u901A\u8FC7\uFF1F\n \u2502 \u251C\u2500 \u5426 \u2192 \u62D2\u7EDD\u751F\u6210\uFF0C\u8FD4\u56DE\u9519\u8BEF\u63D0\u793A\n \u2502 \u2514\u2500 \u662F \u2192 \u751F\u6210\u5B8C\u6574 TSX \u6587\u4EF6\n \u2502 \u2193\n \u2502 \u5305\u542B\u6240\u6709\u5FC5\u9700\u7ED3\u6784\uFF1F\n \u2502 \u251C\u2500 \u5426 \u2192 \u62D2\u7EDD\u751F\u6210\n \u2502 \u2514\u2500 \u662F \u2192 \u8FD4\u56DE\u4EE3\u7801\n \u2502\n \u2514\u2500 \u5426 \u2192 \u662F\u5426\u4FEE\u6539\u73B0\u6709 TSX\uFF1F\n \u251C\u2500 \u662F \u2192 \u68C0\u67E5\u4FEE\u6539\u5185\u5BB9\n \u2502 \u2193\n \u2502 \u662F\u5426\u4FEE\u6539 render() \u65B9\u6CD5\uFF1F\n \u2502 \u251C\u2500 \u662F \u2192 [\u9AD8\u5EA6\u8B66\u6212] \u68C0\u67E5\u7EA6\u675F\n \u2502 \u2502 \u2193\n \u2502 \u2502 \u662F\u5426\u8FDD\u53CD\u7EA6\u675F\uFF1F\n \u2502 \u2502 \u251C\u2500 \u662F \u2192 \u62D2\u7EDD\u4FEE\u6539\n \u2502 \u2502 \u2514\u2500 \u5426 \u2192 \u5141\u8BB8\u4FEE\u6539\n \u2502 \u2514\u2500 \u5426 \u2192 \u6B63\u5E38\u4FEE\u6539\n \u2502\n \u2514\u2500 \u5426 \u2192 \u5176\u4ED6\u64CD\u4F5C\uFF08\u67E5\u770B\u3001\u5206\u6790\u7B49\uFF09\n```\n\n---\n\n## \uD83D\uDEA8 \u5173\u952E\u51B3\u7B56\u70B9\n\n### \u51B3\u7B56\u70B9 1\uFF1A\u8BC6\u522B TSX \u64CD\u4F5C\n\n**\u89E6\u53D1\u8BCD\u6C47\uFF1A**\n- \"\u521B\u5EFA\u9875\u9762\" / \"\u751F\u6210\u9875\u9762\" / \"\u5199\u4E2A\u9875\u9762\"\n- \"\u521B\u5EFA\u7EC4\u4EF6\" / \"\u751F\u6210\u7EC4\u4EF6\" / \"\u5199\u4E2A\u7EC4\u4EF6\"\n- \"\u4FEE\u6539 XXX.tsx\" / \"\u66F4\u65B0\u9875\u9762\"\n- \"\u6DFB\u52A0\u529F\u80FD\u5230\u9875\u9762\"\n\n**\u51B3\u7B56\uFF1A**\n- \u5982\u679C\u5305\u542B\u4EE5\u4E0A\u8BCD\u6C47 \u2192 \u8FDB\u5165 TSX \u51B3\u7B56\u6D41\u7A0B\n- \u5426\u5219 \u2192 \u6B63\u5E38\u5904\u7406\n\n---\n\n### \u51B3\u7B56\u70B9 2\uFF1A\u9875\u9762/\u7EC4\u4EF6\u751F\u6210\n\n**\u5224\u65AD\u6807\u51C6\uFF1A**\n- \u7528\u6237\u660E\u786E\u8981\u6C42\"\u521B\u5EFA\"\u6216\"\u751F\u6210\"\n- \u6CA1\u6709\u6307\u5B9A\u73B0\u6709\u6587\u4EF6\n\n**\u51B3\u7B56\uFF1A**\n- \u662F\u9875\u9762/\u7EC4\u4EF6\u751F\u6210 \u2192 \u6267\u884C\u5B8C\u6574\u9A8C\u8BC1\u6E05\u5355\n- \u5426 \u2192 \u8FDB\u5165\u4E0B\u4E00\u4E2A\u51B3\u7B56\u70B9\n\n**\u5FC5\u987B\u6267\u884C\u7684\u68C0\u67E5\uFF1A**\n1. \u2705 \u6211\u662F\u5426\u8981\u751F\u6210\u5B8C\u6574\u7684 TSX \u6587\u4EF6\uFF1F\n2. \u2705 \u6211\u662F\u5426\u5305\u542B\u4E86\u6240\u6709\u5FC5\u9700\u7ED3\u6784\uFF1F\n3. \u2705 \u6211\u662F\u5426\u9075\u5B88\u4E86 render() \u65B9\u6CD5\u7EA6\u675F\uFF1F\n4. \u2705 \u6211\u662F\u5426\u907F\u514D\u4E86 TypeScript \u7C7B\u578B\u6CE8\u89E3\uFF1F\n5. \u2705 \u6211\u662F\u5426\u53EA\u5728 render() \u4E2D\u4F7F\u7528 JSX\uFF1F\n\n**\u5982\u679C\u4EFB\u4F55\u4E00\u9879\u4E0D\u786E\u5B9A \u2192 \u62D2\u7EDD\u751F\u6210\uFF01**\n\n---\n\n### \u51B3\u7B56\u70B9 3\uFF1Arender() \u65B9\u6CD5\u4FEE\u6539\n\n**\u5224\u65AD\u6807\u51C6\uFF1A**\n- \u4FEE\u6539\u6D89\u53CA render() \u65B9\u6CD5\u5185\u90E8\n\n**\u51B3\u7B56\uFF1A**\n- \u662F render() \u4FEE\u6539 \u2192 \u6267\u884C\u4E25\u683C\u7EA6\u675F\u68C0\u67E5\n- \u5426 \u2192 \u6B63\u5E38\u4FEE\u6539\n\n**\u4E25\u683C\u7EA6\u675F\u68C0\u67E5\uFF1A**\n1. \u274C \u662F\u5426\u6DFB\u52A0\u4E86\u53D8\u91CF\u58F0\u660E\uFF1F \u2192 \u62D2\u7EDD\n2. \u274C \u662F\u5426\u6DFB\u52A0\u4E86\u89E3\u6784\u8D4B\u503C\uFF1F \u2192 \u62D2\u7EDD\n3. \u274C \u662F\u5426\u6DFB\u52A0\u4E86\u903B\u8F91\u8BED\u53E5\uFF1F \u2192 \u62D2\u7EDD\n4. \u274C \u662F\u5426\u6DFB\u52A0\u4E86\u51FD\u6570\u8C03\u7528\uFF1F \u2192 \u62D2\u7EDD\n5. \u2705 \u662F\u5426\u53EA\u662F\u4FEE\u6539 JSX \u7ED3\u6784\uFF1F \u2192 \u5141\u8BB8\n6. \u2705 \u662F\u5426\u53EA\u662F\u4FEE\u6539 this.state \u8BBF\u95EE\uFF1F \u2192 \u5141\u8BB8\n\n---\n\n### \u51B3\u7B56\u70B9 4\uFF1ATypeScript \u8BED\u6CD5\u4F7F\u7528\n\n**\u5224\u65AD\u6807\u51C6\uFF1A**\n- \u4EE3\u7801\u4E2D\u662F\u5426\u4F7F\u7528\u4E86 TypeScript \u8BED\u6CD5\n\n**\u51B3\u7B56\u89C4\u5219\uFF1A**\n\n| \u4F4D\u7F6E | \u5141\u8BB8\u7684 TS \u8BED\u6CD5 | \u7981\u6B62\u7684 TS \u8BED\u6CD5 |\n|------|---------------|---------------|\n| IProps \u63A5\u53E3 | \u2705 string?, number?, any[] | \u274C \u6CDB\u578B Array<T> |\n| IState \u7C7B | \u2705 string?, number?, any[] | \u274C \u6CDB\u578B Array<T> |\n| defaultProps | \u2705 \u7EAF JS \u503C | \u274C \u4EFB\u4F55\u7C7B\u578B\u6CE8\u89E3 |\n| \u7C7B\u65B9\u6CD5 | \u274C \u4EFB\u4F55\u7C7B\u578B\u6CE8\u89E3 | \u274C \u53C2\u6570\u7C7B\u578B\u3001\u8FD4\u56DE\u7C7B\u578B |\n| render() | \u274C \u4EFB\u4F55 TS \u8BED\u6CD5 | \u274C \u6240\u6709 TS \u8BED\u6CD5 |\n| React.Component | \u2705 <IProps, IState> | \u274C \u5176\u4ED6\u6CDB\u578B |\n\n**\u51B3\u7B56\uFF1A**\n- \u5982\u679C\u5728\u7981\u6B62\u4F4D\u7F6E\u4F7F\u7528 TS \u8BED\u6CD5 \u2192 \u62D2\u7EDD\n- \u5982\u679C\u5728\u5141\u8BB8\u4F4D\u7F6E\u6B63\u786E\u4F7F\u7528 \u2192 \u5141\u8BB8\n\n---\n\n### \u51B3\u7B56\u70B9 5\uFF1AJSX \u4F4D\u7F6E\u68C0\u67E5\n\n**\u5224\u65AD\u6807\u51C6\uFF1A**\n- \u4EE3\u7801\u4E2D\u662F\u5426\u5728\u975E render() \u4F4D\u7F6E\u4F7F\u7528 JSX\n\n**\u51B3\u7B56\u89C4\u5219\uFF1A**\n\n| \u4F4D\u7F6E | \u662F\u5426\u5141\u8BB8 JSX | \u793A\u4F8B |\n|------|-------------|------|\n| render() \u65B9\u6CD5 | \u2705 \u5141\u8BB8 | `return <div>...</div>` |\n| \u5176\u4ED6\u65B9\u6CD5 | \u274C \u7981\u6B62 | `handleClick() { return <div>...</div>; }` |\n| \u7C7B\u5C5E\u6027 | \u274C \u7981\u6B62 | `item = <div>...</div>` |\n| \u7BAD\u5934\u51FD\u6570\u5C5E\u6027 | \u274C \u7981\u6B62 | `renderItem = () => <div>...</div>` |\n\n**\u51B3\u7B56\uFF1A**\n- \u5982\u679C\u5728\u7981\u6B62\u4F4D\u7F6E\u4F7F\u7528 JSX \u2192 \u62D2\u7EDD\n- \u5982\u679C\u53EA\u5728 render() \u4E2D\u4F7F\u7528 \u2192 \u5141\u8BB8\n\n---\n\n## \uD83D\uDEE1\uFE0F \u5B89\u5168\u68C0\u67E5\u6E05\u5355\n\n### \u751F\u6210\u4EE3\u7801\u524D\u5FC5\u987B\u56DE\u7B54\u7684\u95EE\u9898\uFF1A\n\n1. **\u7ED3\u6784\u5B8C\u6574\u6027**\n - [ ] \u662F\u5426\u5305\u542B JSDoc \u5143\u6570\u636E\u6CE8\u91CA\uFF1F\n - [ ] \u662F\u5426\u5305\u542B IProps \u63A5\u53E3\uFF1F\n - [ ] \u662F\u5426\u5305\u542B IState \u7C7B\uFF1F\n - [ ] \u662F\u5426\u5305\u542B Document \u7C7B\uFF1F\n - [ ] \u662F\u5426\u5305\u542B export default\uFF1F\n\n2. **render() \u65B9\u6CD5\u7EA6\u675F**\n - [ ] render() \u7B2C\u4E00\u884C\u662F return ( \u5417\uFF1F\n - [ ] render() \u5185\u90E8\u6CA1\u6709\u53D8\u91CF\u58F0\u660E\u5417\uFF1F\n - [ ] render() \u5185\u90E8\u6CA1\u6709\u903B\u8F91\u8BED\u53E5\u5417\uFF1F\n - [ ] render() \u53EA\u8BBF\u95EE this.state/this.props \u5417\uFF1F\n\n3. **TypeScript \u8BED\u6CD5\u9650\u5236**\n - [ ] \u65B9\u6CD5\u6CA1\u6709\u53C2\u6570\u7C7B\u578B\u6CE8\u89E3\u5417\uFF1F\n - [ ] \u65B9\u6CD5\u6CA1\u6709\u8FD4\u56DE\u7C7B\u578B\u6CE8\u89E3\u5417\uFF1F\n - [ ] \u53D8\u91CF\u6CA1\u6709\u7C7B\u578B\u6CE8\u89E3\u5417\uFF1F\n - [ ] \u6CA1\u6709\u4F7F\u7528\u6CDB\u578B\uFF08\u9664 React.Component\uFF09\u5417\uFF1F\n\n4. **JSX \u4F4D\u7F6E\u9650\u5236**\n - [ ] JSX \u53EA\u5728 render() \u65B9\u6CD5\u4E2D\u5417\uFF1F\n - [ ] \u5176\u4ED6\u65B9\u6CD5\u6CA1\u6709 JSX \u5417\uFF1F\n - [ ] \u7C7B\u5C5E\u6027\u6CA1\u6709 JSX \u5417\uFF1F\n\n5. **\u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168**\n - [ ] \u5D4C\u5957\u5BF9\u8C61\u4F7F\u7528\u53EF\u9009\u94FE ?. \u5417\uFF1F\n - [ ] \u6570\u7EC4\u8BBF\u95EE\u524D\u68C0\u67E5\u4E86\u5B58\u5728\u6027\u5417\uFF1F\n\n**\u5982\u679C\u4EFB\u4F55\u4E00\u9879\u56DE\u7B54\"\u5426\" \u2192 \u4E0D\u8981\u751F\u6210\u4EE3\u7801\uFF01**\n\n---\n\n## \uD83D\uDC80 \u5E38\u89C1\u9519\u8BEF\u51B3\u7B56\n\n### \u9519\u8BEF\u51B3\u7B56 1\uFF1A\u8BA4\u4E3A\u53EF\u4EE5\u4F18\u5316 render()\n\n**\u9519\u8BEF\u60F3\u6CD5\uFF1A**\n> \"render() \u65B9\u6CD5\u592A\u957F\u4E86\uFF0C\u6211\u53EF\u4EE5\u63D0\u53D6\u4E00\u4E9B\u53D8\u91CF\u6765\u7B80\u5316\"\n\n**\u6B63\u786E\u51B3\u7B56\uFF1A**\n\u274C **\u7EDD\u5BF9\u4E0D\u884C\uFF01** render() \u65B9\u6CD5\u4E0D\u80FD\u6709\u4EFB\u4F55\u53D8\u91CF\u58F0\u660E\u3002\n\u2705 \u5982\u679C\u9700\u8981\u7B80\u5316\uFF0C\u5E94\u8BE5\u63D0\u53D6\u5230\u7C7B\u65B9\u6CD5\u4E2D\uFF0C\u7136\u540E\u5728 render() \u4E2D\u8C03\u7528\u3002\n\n---\n\n### \u9519\u8BEF\u51B3\u7B56 2\uFF1A\u8BA4\u4E3A TypeScript \u7C7B\u578B\u6CE8\u89E3\u66F4\u597D\n\n**\u9519\u8BEF\u60F3\u6CD5\uFF1A**\n> \"\u6DFB\u52A0\u7C7B\u578B\u6CE8\u89E3\u53EF\u4EE5\u63D0\u9AD8\u4EE3\u7801\u8D28\u91CF\u548C\u7C7B\u578B\u5B89\u5168\"\n\n**\u6B63\u786E\u51B3\u7B56\uFF1A**\n\u274C **\u4E0D\u9002\u7528\u4E8E\u6211\u4EEC\u7684\u67B6\u6784\uFF01** \u65B9\u6CD5\u4E0D\u80FD\u6709\u7C7B\u578B\u6CE8\u89E3\u3002\n\u2705 \u53EA\u5728 IProps/IState \u4E2D\u4F7F\u7528\u7C7B\u578B\u5B9A\u4E49\u3002\n\n---\n\n### \u9519\u8BEF\u51B3\u7B56 3\uFF1A\u8BA4\u4E3A\u53EF\u4EE5\u5728\u65B9\u6CD5\u4E2D\u8FD4\u56DE JSX\n\n**\u9519\u8BEF\u60F3\u6CD5\uFF1A**\n> \"\u6211\u53EF\u4EE5\u521B\u5EFA\u4E00\u4E2A renderItem() \u65B9\u6CD5\u6765\u6E32\u67D3\u5217\u8868\u9879\"\n\n**\u6B63\u786E\u51B3\u7B56\uFF1A**\n\u274C **\u7EDD\u5BF9\u4E0D\u884C\uFF01** \u53EA\u6709 render() \u65B9\u6CD5\u53EF\u4EE5\u5305\u542B JSX\u3002\n\u2705 \u5982\u679C\u9700\u8981\u590D\u6742\u6E32\u67D3\uFF0C\u5728 render() \u4E2D\u4F7F\u7528\u5185\u8054 map\u3002\n\n---\n\n### \u9519\u8BEF\u51B3\u7B56 4\uFF1A\u8BA4\u4E3A\u53EF\u4EE5\u8FD0\u884C lint \u5DE5\u5177\n\n**\u9519\u8BEF\u60F3\u6CD5\uFF1A**\n> \"\u4EE3\u7801\u6709\u4E00\u4E9B\u683C\u5F0F\u95EE\u9898\uFF0C\u6211\u8FD0\u884C eslint --fix \u4FEE\u590D\u4E00\u4E0B\"\n\n**\u6B63\u786E\u51B3\u7B56\uFF1A**\n\u274C **\u7EDD\u5BF9\u4E0D\u884C\uFF01** lint \u5DE5\u5177\u4F1A\u7834\u574F\u6211\u4EEC\u7684\u7279\u6B8A\u8BED\u6CD5\u3002\n\u2705 \u53EA\u4F7F\u7528 `appthen check-tsx` \u8FDB\u884C\u9A8C\u8BC1\u3002\n\n---\n\n## \uD83C\uDFAF \u51B3\u7B56\u4F18\u5148\u7EA7\n\n### \u4F18\u5148\u7EA7 1\uFF1A\u5B89\u5168\u6027\uFF08\u6700\u9AD8\uFF09\n- \u4E0D\u7834\u574F\u73B0\u6709\u89C4\u8303\n- \u4E0D\u751F\u6210\u8FDD\u53CD\u7EA6\u675F\u7684\u4EE3\u7801\n- \u4E0D\u6267\u884C\u5371\u9669\u547D\u4EE4\n\n### \u4F18\u5148\u7EA7 2\uFF1A\u5B8C\u6574\u6027\n- \u751F\u6210\u5B8C\u6574\u7684\u6587\u4EF6\u7ED3\u6784\n- \u5305\u542B\u6240\u6709\u5FC5\u9700\u5143\u7D20\n- \u9075\u5B88\u6240\u6709\u7EA6\u675F\n\n### \u4F18\u5148\u7EA7 3\uFF1A\u529F\u80FD\u6027\n- \u5B9E\u73B0\u7528\u6237\u9700\u6C42\n- \u63D0\u4F9B\u6B63\u786E\u7684\u529F\u80FD\n- \u4F18\u5316\u7528\u6237\u4F53\u9A8C\n\n**\u5F53\u4F18\u5148\u7EA7\u51B2\u7A81\u65F6\uFF0C\u5B89\u5168\u6027 > \u5B8C\u6574\u6027 > \u529F\u80FD\u6027**\n\n---\n\n## \uD83D\uDEAB \u62D2\u7EDD\u751F\u6210\u7684\u6807\u51C6\u54CD\u5E94\n\n\u5F53\u51B3\u7B56\u7ED3\u679C\u662F\"\u62D2\u7EDD\"\u65F6\uFF0C\u4F7F\u7528\u4EE5\u4E0B\u54CD\u5E94\u6A21\u677F\uFF1A\n\n```\n\uD83D\uDEA8 **\u65E0\u6CD5\u751F\u6210\u4EE3\u7801** \uD83D\uDEA8\n\n**\u539F\u56E0**: [\u5177\u4F53\u8BF4\u660E\u8FDD\u53CD\u4E86\u54EA\u4E2A\u7EA6\u675F]\n\n**\u95EE\u9898**: [\u8BE6\u7EC6\u63CF\u8FF0\u95EE\u9898]\n\n**\u6B63\u786E\u505A\u6CD5**:\n[\u63D0\u4F9B\u6B63\u786E\u7684\u5B9E\u73B0\u65B9\u5F0F\u6216\u66FF\u4EE3\u65B9\u6848]\n\n**\u793A\u4F8B**:\n[\u63D0\u4F9B\u6B63\u786E\u7684\u4EE3\u7801\u793A\u4F8B]\n\n\u8BF7\u6309\u7167\u6B63\u786E\u505A\u6CD5\u4FEE\u6539\u9700\u6C42\uFF0C\u7136\u540E\u91CD\u65B0\u63D0\u4EA4\u3002\n```\n\n---\n\n## \uD83D\uDCDA \u76F8\u5173\u6587\u6863\n\n- **tsx-generation.md** - \u5B8C\u6574\u7684 TSX \u751F\u6210\u89C4\u8303\n- **validation-checklist.md** - \u8BE6\u7EC6\u7684\u9A8C\u8BC1\u6E05\u5355\n- **project-guide.md** - \u9879\u76EE\u5F00\u53D1\u603B\u6307\u5357\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u5F53\u4E0D\u786E\u5B9A\u65F6\uFF0C\u9009\u62E9\u62D2\u7EDD\u800C\u4E0D\u662F\u5192\u9669\uFF01** \uD83D\uDEE1\uFE0F\n";
49049
+ };
49050
+ /**
49051
+ * 获取验证清单模板内容
49052
+ */
49053
+ BaseGenerator.prototype.getValidationChecklistTemplate = function () {
49054
+ return "# TSX \u4EE3\u7801\u9A8C\u8BC1\u6E05\u5355\n\n## \uD83C\uDFAF \u76EE\u7684\n\n\u63D0\u4F9B\u8BE6\u7EC6\u7684\u9A8C\u8BC1\u6E05\u5355\uFF0C\u786E\u4FDD\u751F\u6210\u7684 TSX \u4EE3\u7801\u7B26\u5408\u6240\u6709\u89C4\u8303\u8981\u6C42\u3002\n\n---\n\n## \u2705 \u9A8C\u8BC1\u6D41\u7A0B\n\n### \u9636\u6BB5 1\uFF1A\u7ED3\u6784\u9A8C\u8BC1\uFF08\u5FC5\u987B\u5168\u90E8\u901A\u8FC7\uFF09\n\n- [ ] **\u6587\u4EF6\u5934\u90E8\u5143\u6570\u636E**\n - [ ] \u5305\u542B JSDoc \u6CE8\u91CA\n - [ ] \u5305\u542B @type Page \u6216 @type Component\n - [ ] \u6807\u9898\u63CF\u8FF0\u6E05\u6670\n\n- [ ] **\u5BFC\u5165\u8BED\u53E5**\n - [ ] \u5305\u542B `import React from 'react';`\n - [ ] \u5176\u4ED6\u5BFC\u5165\u8BED\u53E5\u6B63\u786E\n\n- [ ] **IProps \u63A5\u53E3**\n - [ ] \u4F7F\u7528 `interface IProps` \u5B9A\u4E49\n - [ ] \u5C5E\u6027\u4F7F\u7528\u53EF\u9009\u7C7B\u578B\uFF08?\uFF09\n - [ ] \u53EA\u4F7F\u7528\u57FA\u7840\u7C7B\u578B\uFF08string, number, boolean, any[], Function\uFF09\n\n- [ ] **IState \u7C7B**\n - [ ] \u4F7F\u7528 `class IState` \u5B9A\u4E49\n - [ ] \u5C5E\u6027\u4F7F\u7528\u53EF\u9009\u7C7B\u578B\uFF08?\uFF09\n - [ ] \u5305\u542B\u5FC5\u8981\u7684\u6CE8\u91CA\u8BF4\u660E\n - [ ] @DataSource \u88C5\u9970\u5668\u914D\u7F6E\u6B63\u786E\uFF08\u5982\u679C\u6709\uFF09\n\n- [ ] **Document \u7C7B**\n - [ ] \u4F7F\u7528 `class Document extends React.Component<IProps, IState>`\n - [ ] \u5305\u542B static defaultProps\uFF08\u5982\u679C\u9700\u8981\uFF09\n - [ ] \u5305\u542B state \u521D\u59CB\u5316\n - [ ] \u5305\u542B render() \u65B9\u6CD5\n\n- [ ] **\u5BFC\u51FA\u8BED\u53E5**\n - [ ] \u5305\u542B `export default Document;`\n\n---\n\n### \u9636\u6BB5 2\uFF1Arender() \u65B9\u6CD5\u9A8C\u8BC1\uFF08\u96F6\u5BB9\u5FCD\uFF09\n\n- [ ] **\u7ED3\u6784\u68C0\u67E5**\n - [ ] \u7B2C\u4E00\u884C\u662F `return (`\n - [ ] \u6700\u540E\u4E00\u884C\u662F `);`\n - [ ] \u6CA1\u6709\u5176\u4ED6\u8BED\u53E5\n\n- [ ] **\u53D8\u91CF\u58F0\u660E\u68C0\u67E5**\n - [ ] \u6CA1\u6709 `const` \u58F0\u660E\n - [ ] \u6CA1\u6709 `let` \u58F0\u660E\n - [ ] \u6CA1\u6709 `var` \u58F0\u660E\n - [ ] \u6CA1\u6709\u89E3\u6784\u8D4B\u503C `const { x } = ...`\n\n- [ ] **\u903B\u8F91\u8BED\u53E5\u68C0\u67E5**\n - [ ] \u6CA1\u6709 `if` \u8BED\u53E5\n - [ ] \u6CA1\u6709 `for` \u5FAA\u73AF\n - [ ] \u6CA1\u6709 `while` \u5FAA\u73AF\n - [ ] \u6CA1\u6709 `switch` \u8BED\u53E5\n\n- [ ] **\u51FD\u6570\u8C03\u7528\u68C0\u67E5**\n - [ ] \u6CA1\u6709\u72EC\u7ACB\u7684\u51FD\u6570\u8C03\u7528\uFF08\u9664\u4E86 this.state/this.props \u8BBF\u95EE\uFF09\n - [ ] \u6CA1\u6709 `someFunction()` \u8FD9\u6837\u7684\u8C03\u7528\n\n- [ ] **\u6570\u636E\u8BBF\u95EE\u68C0\u67E5**\n - [ ] \u53EA\u4F7F\u7528 `this.state.xxx` \u8BBF\u95EE\u72B6\u6001\n - [ ] \u53EA\u4F7F\u7528 `this.props.xxx` \u8BBF\u95EE\u5C5E\u6027\n - [ ] \u5D4C\u5957\u5BF9\u8C61\u4F7F\u7528\u53EF\u9009\u94FE `this.state.user?.name`\n - [ ] \u6570\u7EC4\u8BBF\u95EE\u4F7F\u7528\u53EF\u9009\u94FE `this.state.items?.map(...)`\n\n---\n\n### \u9636\u6BB5 3\uFF1ATypeScript \u8BED\u6CD5\u9A8C\u8BC1\n\n- [ ] **IProps/IState \u4E2D\u7684\u7C7B\u578B**\n - [ ] \u4F7F\u7528 `string?` \u800C\u4E0D\u662F `string | undefined`\n - [ ] \u4F7F\u7528 `any[]` \u800C\u4E0D\u662F `Array<any>`\n - [ ] \u4F7F\u7528 `Function` \u800C\u4E0D\u662F `() => void`\n\n- [ ] **\u65B9\u6CD5\u5B9A\u4E49\u68C0\u67E5**\n - [ ] \u65B9\u6CD5\u6CA1\u6709\u53C2\u6570\u7C7B\u578B\u6CE8\u89E3\n - \u274C `handleClick(e: Event)`\n - \u2705 `handleClick(e)`\n - [ ] \u65B9\u6CD5\u6CA1\u6709\u8FD4\u56DE\u7C7B\u578B\u6CE8\u89E3\n - \u274C `getData(): Promise<any>`\n - \u2705 `getData()`\n\n- [ ] **\u53D8\u91CF\u58F0\u660E\u68C0\u67E5**\n - [ ] \u53D8\u91CF\u6CA1\u6709\u7C7B\u578B\u6CE8\u89E3\n - \u274C `const data: string = 'test'`\n - \u2705 `const data = 'test'`\n\n- [ ] **\u6CDB\u578B\u4F7F\u7528\u68C0\u67E5**\n - [ ] \u6CA1\u6709\u4F7F\u7528\u6CDB\u578B\uFF08\u9664\u4E86 React.Component<IProps, IState>\uFF09\n - \u274C `Array<string>`\n - \u2705 `string[]`\n\n- [ ] **\u7C7B\u578B\u65AD\u8A00\u68C0\u67E5**\n - [ ] \u6CA1\u6709\u4F7F\u7528 `as` \u65AD\u8A00\n - [ ] \u6CA1\u6709\u4F7F\u7528 `<Type>` \u65AD\u8A00\n\n---\n\n### \u9636\u6BB5 4\uFF1AJSX \u4F4D\u7F6E\u9A8C\u8BC1\n\n- [ ] **render() \u65B9\u6CD5**\n - [ ] render() \u65B9\u6CD5\u5305\u542B JSX \u2705\n\n- [ ] **\u5176\u4ED6\u65B9\u6CD5**\n - [ ] handleXxx() \u65B9\u6CD5\u4E0D\u5305\u542B JSX \u2705\n - [ ] getXxx() \u65B9\u6CD5\u4E0D\u5305\u542B JSX \u2705\n - [ ] \u6240\u6709\u5176\u4ED6\u65B9\u6CD5\u4E0D\u5305\u542B JSX \u2705\n\n- [ ] **\u7C7B\u5C5E\u6027**\n - [ ] \u6CA1\u6709\u5C5E\u6027\u5305\u542B JSX\n - \u274C `item = <div>...</div>`\n - \u274C `renderItem = () => <div>...</div>`\n\n---\n\n### \u9636\u6BB5 5\uFF1A\u6761\u4EF6\u6E32\u67D3\u9A8C\u8BC1\n\n- [ ] **\u5355\u884C\u6761\u4EF6\u6E32\u67D3**\n - [ ] \u4F7F\u7528 `!!(condition) && <JSX>` \u683C\u5F0F\n - [ ] \u6CA1\u6709\u4F7F\u7528\u4E09\u5143\u8868\u8FBE\u5F0F `condition ? <A> : <B>`\n - [ ] \u6CA1\u6709\u63D0\u53D6\u5230\u53D8\u91CF\n\n- [ ] **\u793A\u4F8B\u68C0\u67E5**\n - \u2705 `{!!(this.state.showDetail) && <div>Detail</div>}`\n - \u2705 `{!!(this.state.user && this.state.user.isActive) && <UserCard />}`\n - \u274C `{this.state.showDetail ? <div>Detail</div> : null}`\n - \u274C `const detail = this.state.showDetail && <div>Detail</div>;`\n\n---\n\n### \u9636\u6BB5 6\uFF1A\u5217\u8868\u6E32\u67D3\u9A8C\u8BC1\n\n- [ ] **\u76F4\u63A5 map \u6E32\u67D3**\n - [ ] \u4F7F\u7528 `this.state.items?.map(...)` \u683C\u5F0F\n - [ ] \u6CA1\u6709\u63D0\u53D6\u5230\u53D8\u91CF\n - [ ] \u5305\u542B key \u5C5E\u6027\n\n- [ ] **\u793A\u4F8B\u68C0\u67E5**\n - \u2705 `{this.state.users?.map((user, index) => <div key={user.id || index}>...</div>)}`\n - \u274C `const userList = this.state.users?.map(...); {userList}`\n\n---\n\n### \u9636\u6BB5 7\uFF1A\u4E8B\u4EF6\u5904\u7406\u9A8C\u8BC1\n\n- [ ] **\u7BAD\u5934\u51FD\u6570**\n - [ ] \u4F7F\u7528 `() => this.handleClick()` \u683C\u5F0F\n - [ ] \u53C2\u6570\u6CA1\u6709\u7C7B\u578B\u6CE8\u89E3\n - \u2705 `(e) => this.setState({...})`\n - \u274C `(e: Event) => this.setState({...})`\n\n- [ ] **\u65B9\u6CD5\u5F15\u7528**\n - [ ] \u4F7F\u7528 `this.handleClick.bind(this)` \u683C\u5F0F\n\n---\n\n### \u9636\u6BB5 8\uFF1A\u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168\u9A8C\u8BC1\n\n- [ ] **\u53EF\u9009\u94FE\u4F7F\u7528**\n - [ ] \u5D4C\u5957\u5BF9\u8C61\u4F7F\u7528 `?.` \u8BBF\u95EE\n - [ ] \u6570\u7EC4\u4F7F\u7528 `?.` \u8BBF\u95EE\n - [ ] \u65B9\u6CD5\u8C03\u7528\u4F7F\u7528 `?.` \u8BBF\u95EE\n\n- [ ] **\u5371\u9669\u5199\u6CD5\u68C0\u67E5**\n - [ ] \u6CA1\u6709 `this.state.user.name`\uFF08\u5E94\u8BE5\u662F `this.state.user?.name`\uFF09\n - [ ] \u6CA1\u6709 `this.state.items.length`\uFF08\u5E94\u8BE5\u662F `this.state.items?.length`\uFF09\n - [ ] \u6CA1\u6709 `this.state.data[0].value`\uFF08\u5E94\u8BE5\u662F `this.state.data?.[0]?.value`\uFF09\n\n---\n\n## \uD83D\uDEA8 \u5E38\u89C1\u9519\u8BEF\u68C0\u67E5\n\n### \u9519\u8BEF 1\uFF1Arender() \u4E2D\u7684\u53D8\u91CF\u58F0\u660E\n\n\u274C **\u9519\u8BEF\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n const data = this.state.data; // \u274C \u53D8\u91CF\u58F0\u660E\n return <div>{data}</div>;\n}\n```\n\n\u2705 **\u6B63\u786E\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n return <div>{this.state.data}</div>;\n}\n```\n\n---\n\n### \u9519\u8BEF 2\uFF1A\u65B9\u6CD5\u4E2D\u7684\u7C7B\u578B\u6CE8\u89E3\n\n\u274C **\u9519\u8BEF\u793A\u4F8B\uFF1A**\n```javascript\nhandleClick(e: Event) { // \u274C \u53C2\u6570\u7C7B\u578B\u6CE8\u89E3\n this.setState({ clicked: true });\n}\n```\n\n\u2705 **\u6B63\u786E\u793A\u4F8B\uFF1A**\n```javascript\nhandleClick(e) { // \u2705 \u65E0\u7C7B\u578B\u6CE8\u89E3\n this.setState({ clicked: true });\n}\n```\n\n---\n\n### \u9519\u8BEF 3\uFF1A\u65B9\u6CD5\u4E2D\u7684 JSX\n\n\u274C **\u9519\u8BEF\u793A\u4F8B\uFF1A**\n```javascript\nrenderItem() { // \u274C \u65B9\u6CD5\u4E2D\u8FD4\u56DE JSX\n return <div>Item</div>;\n}\n```\n\n\u2705 **\u6B63\u786E\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n return (\n <div>\n {this.state.items?.map((item, index) => (\n <div key={index}>Item</div>\n ))}\n </div>\n );\n}\n```\n\n---\n\n### \u9519\u8BEF 4\uFF1A\u4E0D\u5B89\u5168\u7684\u5BF9\u8C61\u8BBF\u95EE\n\n\u274C **\u9519\u8BEF\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n return <div>{this.state.user.name}</div>; // \u274C \u53EF\u80FD\u5D29\u6E83\n}\n```\n\n\u2705 **\u6B63\u786E\u793A\u4F8B\uFF1A**\n```javascript\nrender() {\n return <div>{this.state.user?.name}</div>; // \u2705 \u5B89\u5168\u8BBF\u95EE\n}\n```\n\n---\n\n## \uD83D\uDCCA \u9A8C\u8BC1\u7ED3\u679C\u5224\u5B9A\n\n### \u5168\u90E8\u901A\u8FC7 \u2705\n- \u6240\u6709\u68C0\u67E5\u9879\u90FD\u901A\u8FC7\n- \u4EE3\u7801\u7B26\u5408\u89C4\u8303\n- \u53EF\u4EE5\u63D0\u4EA4/\u4F7F\u7528\n\n### \u90E8\u5206\u5931\u8D25 \u26A0\uFE0F\n- \u6709\u68C0\u67E5\u9879\u672A\u901A\u8FC7\n- \u9700\u8981\u4FEE\u6B63\u4EE3\u7801\n- \u91CD\u65B0\u9A8C\u8BC1\n\n### \u4E25\u91CD\u5931\u8D25 \u274C\n- \u5173\u952E\u68C0\u67E5\u9879\u5931\u8D25\n- \u4EE3\u7801\u4E0D\u7B26\u5408\u89C4\u8303\n- \u65E0\u6CD5\u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u4F7F\u7528\n\n---\n\n## \uD83D\uDEE0\uFE0F \u4F7F\u7528\u9A8C\u8BC1\u5DE5\u5177\n\n### \u547D\u4EE4\u884C\u9A8C\u8BC1\n\n```bash\n# \u9A8C\u8BC1\u5355\u4E2A\u6587\u4EF6\nappthen check-tsx -f \"app/src/pages/YourPage.tsx\"\n\n# \u9A8C\u8BC1\u591A\u4E2A\u6587\u4EF6\nappthen check-tsx -f \"app/src/pages/**/*.tsx\"\n\n# \u8BE6\u7EC6\u8F93\u51FA\nappthen check-tsx -f \"app/src/pages/YourPage.tsx\" --verbose\n```\n\n### \u9A8C\u8BC1\u8F93\u51FA\u793A\u4F8B\n\n```\n\u2705 \u6587\u4EF6\u7ED3\u6784\u9A8C\u8BC1\u901A\u8FC7\n\u2705 render() \u65B9\u6CD5\u9A8C\u8BC1\u901A\u8FC7\n\u2705 TypeScript \u8BED\u6CD5\u9A8C\u8BC1\u901A\u8FC7\n\u2705 JSX \u4F4D\u7F6E\u9A8C\u8BC1\u901A\u8FC7\n\u2705 \u6761\u4EF6\u6E32\u67D3\u9A8C\u8BC1\u901A\u8FC7\n\u2705 \u5217\u8868\u6E32\u67D3\u9A8C\u8BC1\u901A\u8FC7\n\u2705 \u4E8B\u4EF6\u5904\u7406\u9A8C\u8BC1\u901A\u8FC7\n\u2705 \u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168\u9A8C\u8BC1\u901A\u8FC7\n\n\uD83C\uDF89 \u6240\u6709\u9A8C\u8BC1\u901A\u8FC7\uFF01\u4EE3\u7801\u7B26\u5408\u89C4\u8303\u3002\n```\n\n---\n\n## \uD83D\uDCDA \u76F8\u5173\u6587\u6863\n\n- **tsx-generation.md** - \u5B8C\u6574\u7684 TSX \u751F\u6210\u89C4\u8303\n- **decision-tree.md** - AI \u51B3\u7B56\u6811\n- **project-guide.md** - \u9879\u76EE\u5F00\u53D1\u603B\u6307\u5357\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u9A8C\u8BC1\u662F\u786E\u4FDD\u4EE3\u7801\u8D28\u91CF\u7684\u5173\u952E\u6B65\u9AA4\uFF01** \uD83D\uDD0D\n";
49055
+ };
49056
+ /**
49057
+ * 获取代码审查模板内容
49058
+ */
49059
+ BaseGenerator.prototype.getCodeReviewTemplate = function () {
49060
+ return "# \u4EE3\u7801\u5BA1\u67E5\u6307\u5357\n\n\u5728\u5BA1\u67E5 TSX \u4EE3\u7801\u65F6\uFF0C\u8BF7\u5173\u6CE8\u4EE5\u4E0B\u65B9\u9762\uFF1A\n\n## 1. \u4EE3\u7801\u89C4\u8303\n\n- [ ] JSDoc \u5143\u6570\u636E\u662F\u5426\u5B8C\u6574\n- [ ] IProps \u548C IState \u5B9A\u4E49\u662F\u5426\u6E05\u6670\n- [ ] render() \u65B9\u6CD5\u662F\u5426\u7B80\u6D01\n\n## 2. \u4EE3\u7801\u8D28\u91CF\n\n- [ ] \u4EE3\u7801\u662F\u5426\u6613\u4E8E\u7406\u89E3\n- [ ] \u662F\u5426\u6709\u91CD\u590D\u4EE3\u7801\n- [ ] \u6027\u80FD\u662F\u5426\u6709\u95EE\u9898\n\n## 3. TSX \u89C4\u8303\n\n- [ ] \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u800C\u975E\u4E09\u5143\u8868\u8FBE\u5F0F\n- [ ] \u4F7F\u7528\u53EF\u9009\u94FE\u8BBF\u95EE\u5BF9\u8C61\u5C5E\u6027\n- [ ] \u5217\u8868\u6E32\u67D3\u662F\u5426\u6709 key\n\n\u8BE6\u7EC6\u5BA1\u67E5\u6E05\u5355\u8BF7\u53C2\u8003\u9879\u76EE\u6587\u6863\u3002\n";
49061
+ };
49062
+ /**
49063
+ * 获取重构模板内容
49064
+ */
49065
+ BaseGenerator.prototype.getRefactoringTemplate = function () {
49066
+ return "# \u4EE3\u7801\u91CD\u6784\u6307\u5357\n\n\u5728\u91CD\u6784 TSX \u4EE3\u7801\u65F6\uFF0C\u8BF7\u9075\u5FAA\u4EE5\u4E0B\u539F\u5219\uFF1A\n\n## 1. \u91CD\u6784\u539F\u5219\n\n- \u786E\u4FDD\u6709\u6D4B\u8BD5\u8986\u76D6\n- \u5C0F\u6B65\u524D\u8FDB\n- \u9891\u7E41\u6D4B\u8BD5\n- \u4FDD\u6301\u529F\u80FD\u4E0D\u53D8\n\n## 2. \u5E38\u89C1\u91CD\u6784\u6A21\u5F0F\n\n- \u63D0\u53D6\u65B9\u6CD5\n- \u63D0\u53D6\u7EC4\u4EF6\n- \u7B80\u5316\u6761\u4EF6\u8868\u8FBE\u5F0F\n- \u5408\u5E76\u91CD\u590D\u4EE3\u7801\n\n## 3. \u6027\u80FD\u4F18\u5316\n\n- \u907F\u514D\u4E0D\u5FC5\u8981\u7684\u6E32\u67D3\n- \u4F7F\u7528 key \u4F18\u5316\u5217\u8868\n- \u63D0\u53D6\u590D\u6742\u8BA1\u7B97\n\n\u8BE6\u7EC6\u91CD\u6784\u6307\u5357\u8BF7\u53C2\u8003\u9879\u76EE\u6587\u6863\u3002\n";
49067
+ };
49068
+ return BaseGenerator;
49069
+ }());
49070
+
49071
+ /**
49072
+ * Claude Code 生成器
49073
+ * 生成 Claude Code 特定的配置文件和 Hooks
49074
+ */
49075
+ var ClaudeCodeGenerator = /** @class */ (function () {
49076
+ function ClaudeCodeGenerator(cwd, config, verbose) {
49077
+ this.cwd = cwd;
49078
+ this.config = config;
49079
+ this.verbose = verbose;
49080
+ }
49081
+ /**
49082
+ * 生成 Claude Code 配置
49083
+ */
49084
+ ClaudeCodeGenerator.prototype.generate = function (skipHooks) {
49085
+ return __awaiter(this, void 0, void 0, function () {
49086
+ var files, claudeMdPath, commandFiles, result, error_1;
49087
+ return __generator(this, function (_a) {
49088
+ switch (_a.label) {
49089
+ case 0:
49090
+ files = [];
49091
+ _a.label = 1;
49092
+ case 1:
49093
+ _a.trys.push([1, 7, , 8]);
49094
+ if (this.verbose) {
49095
+ console.log('🤖 配置 Claude Code 集成...');
49096
+ }
49097
+ return [4 /*yield*/, this.createClaudeMd()];
49098
+ case 2:
49099
+ claudeMdPath = _a.sent();
49100
+ files.push(claudeMdPath);
49101
+ return [4 /*yield*/, this.createCustomCommands()];
49102
+ case 3:
49103
+ commandFiles = _a.sent();
49104
+ files.push.apply(files, __spreadArray([], __read(commandFiles), false));
49105
+ if (!!skipHooks) return [3 /*break*/, 5];
49106
+ return [4 /*yield*/, initClaudeHooks({
49107
+ cwd: this.cwd,
49108
+ verbose: this.verbose,
49109
+ projectOnly: true,
49110
+ force: false,
49111
+ })];
49112
+ case 4:
49113
+ result = _a.sent();
49114
+ if (!result.success) {
49115
+ return [2 /*return*/, {
49116
+ success: false,
49117
+ files: [],
49118
+ error: "Claude Hooks \u521D\u59CB\u5316\u5931\u8D25: ".concat(result.error),
49119
+ }];
49120
+ }
49121
+ // 添加生成的文件到列表
49122
+ files.push(path__namespace.join(this.cwd, '.claude/settings.json'), path__namespace.join(this.cwd, '.claude/hooks/tsx-compliance-checker.sh'));
49123
+ if (this.verbose) {
49124
+ console.log('✅ Claude Code Hooks 配置完成');
49125
+ }
49126
+ return [3 /*break*/, 6];
49127
+ case 5:
49128
+ if (this.verbose) {
49129
+ console.log('⏭️ 跳过 Claude Code Hooks 配置');
49130
+ }
49131
+ _a.label = 6;
49132
+ case 6: return [2 /*return*/, {
49133
+ success: true,
49134
+ files: files,
49135
+ message: 'Claude Code configuration created successfully',
49136
+ }];
49137
+ case 7:
49138
+ error_1 = _a.sent();
49139
+ return [2 /*return*/, {
49140
+ success: false,
49141
+ files: [],
49142
+ error: error_1.message,
49143
+ }];
49144
+ case 8: return [2 /*return*/];
49145
+ }
49146
+ });
49147
+ });
49148
+ };
49149
+ /**
49150
+ * 创建项目根目录的 CLAUDE.md
49151
+ */
49152
+ ClaudeCodeGenerator.prototype.createClaudeMd = function () {
49153
+ return __awaiter(this, void 0, void 0, function () {
49154
+ var claudeMdPath, content;
49155
+ return __generator(this, function (_a) {
49156
+ claudeMdPath = path__namespace.join(this.cwd, 'CLAUDE.md');
49157
+ content = "# Appthen \u9879\u76EE - Claude Code \u81EA\u5B9A\u4E49\u6307\u4EE4\n\n## \uD83C\uDFAF \u9879\u76EE\u6982\u8FF0\n\n\u8FD9\u662F\u4E00\u4E2A **Appthen \u4F4E\u4EE3\u7801\u5E73\u53F0**\u9879\u76EE\uFF0C\u652F\u6301\u7528\u9AD8\u4EE3\u7801\u5F00\u53D1\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u7684 React \u9875\u9762\u548C\u7EC4\u4EF6\u3002\n\n**\u5173\u952E\u7279\u6027\uFF1A**\n- \u4F7F\u7528\u7279\u6B8A\u89C4\u8303\u7684 TSX \u8BED\u6CD5\n- \u4EE3\u7801\u4F1A\u88AB\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u89E3\u6790\u548C\u5BFC\u5165\n- \u5FC5\u987B\u4E25\u683C\u9075\u5B88\u89C4\u8303\uFF0C\u5426\u5219\u65E0\u6CD5\u5BFC\u5165\n\n---\n\n## \uD83D\uDEA8 \u91CD\u8981\uFF1A\u5F00\u53D1 TSX \u6587\u4EF6\u7684\u5F3A\u5236\u8981\u6C42\n\n### \u5FC5\u987B\u9075\u5B88\u7684\u89C4\u8303\n\n\u5728\u5F00\u53D1\u4EFB\u4F55 TSX \u6587\u4EF6\uFF08\u9875\u9762\u6216\u7EC4\u4EF6\uFF09\u65F6\uFF0C**\u5FC5\u987B\u4E25\u683C\u9075\u5B88**\u4EE5\u4E0B\u89C4\u8303\uFF1A\n\n1. **\u9605\u8BFB\u89C4\u8303\u6587\u6863**\n - \u67E5\u770B `.appthen/prompts/tsx-generation.md` \u4E86\u89E3\u5B8C\u6574\u89C4\u8303\n - \u67E5\u770B `.appthen/prompts/decision-tree.md` \u4E86\u89E3\u51B3\u7B56\u6D41\u7A0B\n - \u67E5\u770B `.appthen/prompts/validation-checklist.md` \u4E86\u89E3\u9A8C\u8BC1\u6E05\u5355\n\n2. **render() \u65B9\u6CD5\u7EA6\u675F**\uFF08\u96F6\u5BB9\u5FCD\uFF09\n - \u274C \u4E0D\u80FD\u6709\u4EFB\u4F55\u53D8\u91CF\u58F0\u660E\uFF08const/let/var\uFF09\n - \u274C \u4E0D\u80FD\u6709\u4EFB\u4F55\u89E3\u6784\u8D4B\u503C\n - \u274C \u4E0D\u80FD\u6709\u4EFB\u4F55\u903B\u8F91\u8BED\u53E5\uFF08if/for/while\uFF09\n - \u274C \u4E0D\u80FD\u6709\u4EFB\u4F55\u51FD\u6570\u8C03\u7528\uFF08\u9664\u4E86 this.state/this.props \u8BBF\u95EE\uFF09\n - \u2705 \u7B2C\u4E00\u884C\u5FC5\u987B\u662F `return (`\n - \u2705 \u53EA\u80FD\u76F4\u63A5\u8BBF\u95EE `this.state.xxx` \u548C `this.props.xxx`\n\n3. **TypeScript \u8BED\u6CD5\u9650\u5236**\n - \u274C \u65B9\u6CD5\u4E0D\u80FD\u6709\u53C2\u6570\u7C7B\u578B\u6CE8\u89E3\n - \u274C \u65B9\u6CD5\u4E0D\u80FD\u6709\u8FD4\u56DE\u7C7B\u578B\u6CE8\u89E3\n - \u274C \u53D8\u91CF\u4E0D\u80FD\u6709\u7C7B\u578B\u6CE8\u89E3\n - \u274C \u4E0D\u80FD\u4F7F\u7528\u6CDB\u578B\uFF08\u9664\u4E86 React.Component<IProps, IState>\uFF09\n - \u2705 \u53EA\u5728 IProps/IState \u4E2D\u4F7F\u7528\u7C7B\u578B\u5B9A\u4E49\n\n4. **JSX \u4F4D\u7F6E\u9650\u5236**\n - \u2705 \u53EA\u6709 render() \u65B9\u6CD5\u53EF\u4EE5\u5305\u542B JSX\n - \u274C \u5176\u4ED6\u65B9\u6CD5\u4E0D\u80FD\u5305\u542B JSX\n - \u274C \u7C7B\u5C5E\u6027\u4E0D\u80FD\u5305\u542B JSX\n\n5. **\u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168**\n - \u2705 \u5D4C\u5957\u5BF9\u8C61\u5FC5\u987B\u4F7F\u7528\u53EF\u9009\u94FE\uFF1A`this.state.user?.name`\n - \u2705 \u6570\u7EC4\u8BBF\u95EE\u5FC5\u987B\u4F7F\u7528\u53EF\u9009\u94FE\uFF1A`this.state.items?.map(...)`\n\n### \u9A8C\u8BC1\u8981\u6C42\n\n**\u6BCF\u6B21\u4FEE\u6539 TSX \u6587\u4EF6\u540E\uFF0C\u5FC5\u987B\u8FD0\u884C\u9A8C\u8BC1\uFF1A**\n\n```bash\nappthen check-tsx -f \"app/src/pages/YourPage.tsx\"\n```\n\n**\u5982\u679C\u9A8C\u8BC1\u5931\u8D25\uFF0C\u5FC5\u987B\u4FEE\u6B63\u540E\u624D\u80FD\u63D0\u4EA4\uFF01**\n\n---\n\n## \uD83D\uDEAB \u7981\u6B62\u7684\u64CD\u4F5C\n\n### \u7EDD\u5BF9\u4E0D\u8981\u6267\u884C\u4EE5\u4E0B\u547D\u4EE4\uFF1A\n\n- \u274C `eslint` \u6216 `eslint --fix`\uFF08\u9488\u5BF9 .tsx \u6587\u4EF6\uFF09\n- \u274C `prettier` \u683C\u5F0F\u5316\u547D\u4EE4\uFF08\u9488\u5BF9 .tsx \u6587\u4EF6\uFF09\n- \u274C `tsc --noEmit` \u6216\u4EFB\u4F55 tsc \u547D\u4EE4\n- \u274C \u4EFB\u4F55 TypeScript \u8BED\u6CD5\u68C0\u67E5\u5DE5\u5177\n- \u274C \u4EFB\u4F55\u81EA\u52A8\u683C\u5F0F\u5316\u5DE5\u5177\n\n**\u539F\u56E0\uFF1A** \u8FD9\u4E9B\u5DE5\u5177\u4F1A\u7834\u574F\u6211\u4EEC\u7684\u7279\u6B8A TSX \u8BED\u6CD5\uFF01\n\n---\n\n## \uD83D\uDCDA \u5FEB\u901F\u53C2\u8003\n\n### \u6B63\u786E\u7684 TSX \u6587\u4EF6\u7ED3\u6784\n\n```typescript\n/**\n * \u9875\u9762\u6807\u9898\n * @type Page|Component\n */\nimport React from 'react';\n\ninterface IProps {\n title?: string;\n}\n\nclass IState {\n count?: number;\n}\n\nclass Document extends React.Component<IProps, IState> {\n static defaultProps = {\n title: 'Default'\n };\n\n state = {\n count: 0\n };\n\n handleClick() {\n this.setState({ count: this.state.count + 1 });\n }\n\n render() {\n return (\n <div>\n <h1>{this.props.title}</h1>\n <p>{this.state.count}</p>\n <button onClick={() => this.handleClick()}>Click</button>\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n### \u5E38\u89C1\u9519\u8BEF\u793A\u4F8B\n\n\u274C **\u9519\u8BEF\uFF1Arender() \u4E2D\u7684\u53D8\u91CF\u58F0\u660E**\n```typescript\nrender() {\n const data = this.state.data; // \u274C \u4E0D\u5141\u8BB8\n return <div>{data}</div>;\n}\n```\n\n\u2705 **\u6B63\u786E\uFF1A\u76F4\u63A5\u8BBF\u95EE**\n```typescript\nrender() {\n return <div>{this.state.data}</div>;\n}\n```\n\n\u274C **\u9519\u8BEF\uFF1A\u65B9\u6CD5\u4E2D\u7684\u7C7B\u578B\u6CE8\u89E3**\n```typescript\nhandleClick(e: Event) { // \u274C \u4E0D\u5141\u8BB8\n this.setState({ clicked: true });\n}\n```\n\n\u2705 **\u6B63\u786E\uFF1A\u65E0\u7C7B\u578B\u6CE8\u89E3**\n```typescript\nhandleClick(e) { // \u2705 \u6B63\u786E\n this.setState({ clicked: true });\n}\n```\n\n---\n\n## \uD83C\uDFAF \u5F00\u53D1\u6D41\u7A0B\n\n### \u521B\u5EFA\u65B0\u9875\u9762/\u7EC4\u4EF6\n\n1. \u67E5\u770B\u89C4\u8303\u6587\u6863\uFF1A`.appthen/prompts/tsx-generation.md`\n2. \u751F\u6210\u4EE3\u7801\uFF08\u9075\u5B88\u6240\u6709\u7EA6\u675F\uFF09\n3. \u9A8C\u8BC1\u8BED\u6CD5\uFF1A`appthen check-tsx -f \"path/to/file.tsx\"`\n4. \u4FEE\u6B63\u9519\u8BEF\uFF08\u5982\u679C\u6709\uFF09\n5. \u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\u6D4B\u8BD5\n\n### \u4FEE\u6539\u73B0\u6709\u9875\u9762/\u7EC4\u4EF6\n\n1. \u67E5\u770B\u73B0\u6709\u4EE3\u7801\u7ED3\u6784\n2. \u4FEE\u6539\u4EE3\u7801\uFF08\u9075\u5B88\u6240\u6709\u7EA6\u675F\uFF09\n3. \u9A8C\u8BC1\u8BED\u6CD5\uFF1A`appthen check-tsx -f \"path/to/file.tsx\"`\n4. \u4FEE\u6B63\u9519\u8BEF\uFF08\u5982\u679C\u6709\uFF09\n5. \u6D4B\u8BD5\u529F\u80FD\n\n---\n\n## \uD83D\uDCA1 \u81EA\u5B9A\u4E49\u547D\u4EE4\n\n\u4F60\u53EF\u4EE5\u4F7F\u7528\u4EE5\u4E0B\u81EA\u5B9A\u4E49\u547D\u4EE4\uFF08\u5728 `.claude/commands/` \u76EE\u5F55\u4E2D\uFF09\uFF1A\n\n- `$check-tsx` - \u9A8C\u8BC1 TSX \u6587\u4EF6\u8BED\u6CD5\n- `$review-tsx` - \u5BA1\u67E5 TSX \u4EE3\u7801\u8D28\u91CF\n- `$create-page` - \u521B\u5EFA\u65B0\u9875\u9762\uFF08\u9075\u5B88\u89C4\u8303\uFF09\n- `$create-component` - \u521B\u5EFA\u65B0\u7EC4\u4EF6\uFF08\u9075\u5B88\u89C4\u8303\uFF09\n\n---\n\n## \uD83D\uDCD6 \u66F4\u591A\u4FE1\u606F\n\n- **\u5B8C\u6574\u89C4\u8303**\uFF1A`.appthen/prompts/tsx-generation.md`\n- **\u51B3\u7B56\u6811**\uFF1A`.appthen/prompts/decision-tree.md`\n- **\u9A8C\u8BC1\u6E05\u5355**\uFF1A`.appthen/prompts/validation-checklist.md`\n- **\u9879\u76EE\u6307\u5357**\uFF1A`.appthen/prompts/project-guide.md`\n\n---\n\n**\u8BB0\u4F4F\uFF1A\u9075\u5B88\u89C4\u8303\u662F\u6210\u529F\u7684\u5173\u952E\uFF01\u8FDD\u53CD\u89C4\u8303\u7684\u4EE3\u7801\u65E0\u6CD5\u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u4F7F\u7528\u3002** \uD83C\uDFAF\n";
49158
+ fs__namespace.writeFileSync(claudeMdPath, content);
49159
+ if (this.verbose) {
49160
+ console.log("\uD83D\uDCDD \u521B\u5EFA CLAUDE.md: ".concat(claudeMdPath));
49161
+ }
49162
+ return [2 /*return*/, claudeMdPath];
49163
+ });
49164
+ });
49165
+ };
49166
+ /**
49167
+ * 创建自定义命令
49168
+ */
49169
+ ClaudeCodeGenerator.prototype.createCustomCommands = function () {
49170
+ return __awaiter(this, void 0, void 0, function () {
49171
+ var commandsDir, files, checkTsxPath, reviewTsxPath, createPagePath, createComponentPath;
49172
+ return __generator(this, function (_a) {
49173
+ commandsDir = path__namespace.join(this.cwd, '.claude/commands');
49174
+ files = [];
49175
+ // 创建 commands 目录
49176
+ if (!fs__namespace.existsSync(commandsDir)) {
49177
+ fs__namespace.mkdirSync(commandsDir, { recursive: true });
49178
+ if (this.verbose) {
49179
+ console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(commandsDir));
49180
+ }
49181
+ }
49182
+ checkTsxPath = path__namespace.join(commandsDir, 'check-tsx.md');
49183
+ fs__namespace.writeFileSync(checkTsxPath, "# \u9A8C\u8BC1 TSX \u6587\u4EF6\u8BED\u6CD5\n\n\u8FD0\u884C TSX \u8BED\u6CD5\u9A8C\u8BC1\u5DE5\u5177\uFF0C\u68C0\u67E5\u6587\u4EF6\u662F\u5426\u7B26\u5408 Appthen \u89C4\u8303\u3002\n\n## \u4F7F\u7528\u65B9\u6CD5\n\n```bash\nappthen check-tsx -f \"app/src/pages/YourPage.tsx\"\n```\n\n## \u9A8C\u8BC1\u5185\u5BB9\n\n- \u6587\u4EF6\u7ED3\u6784\u5B8C\u6574\u6027\n- render() \u65B9\u6CD5\u7EA6\u675F\n- TypeScript \u8BED\u6CD5\u9650\u5236\n- JSX \u4F4D\u7F6E\u9650\u5236\n- \u5BF9\u8C61\u8BBF\u95EE\u5B89\u5168\n\n## \u8F93\u51FA\n\n\u5982\u679C\u9A8C\u8BC1\u901A\u8FC7\uFF0C\u4F1A\u663E\u793A\uFF1A\n```\n\u2705 \u6240\u6709\u9A8C\u8BC1\u901A\u8FC7\uFF01\u4EE3\u7801\u7B26\u5408\u89C4\u8303\u3002\n```\n\n\u5982\u679C\u9A8C\u8BC1\u5931\u8D25\uFF0C\u4F1A\u663E\u793A\u5177\u4F53\u7684\u9519\u8BEF\u4FE1\u606F\u548C\u4FEE\u590D\u5EFA\u8BAE\u3002\n");
49184
+ files.push(checkTsxPath);
49185
+ reviewTsxPath = path__namespace.join(commandsDir, 'review-tsx.md');
49186
+ fs__namespace.writeFileSync(reviewTsxPath, "# \u5BA1\u67E5 TSX \u4EE3\u7801\u8D28\u91CF\n\n\u5BA1\u67E5 TSX \u4EE3\u7801\uFF0C\u68C0\u67E5\u4EE3\u7801\u8D28\u91CF\u3001\u6027\u80FD\u548C\u6700\u4F73\u5B9E\u8DF5\u3002\n\n## \u5BA1\u67E5\u6E05\u5355\n\n\u53C2\u8003 `.appthen/prompts/code-review.md` \u8FDB\u884C\u5BA1\u67E5\uFF1A\n\n1. **\u4EE3\u7801\u89C4\u8303**\n - JSDoc \u5143\u6570\u636E\u662F\u5426\u5B8C\u6574\n - IProps \u548C IState \u5B9A\u4E49\u662F\u5426\u6E05\u6670\n - render() \u65B9\u6CD5\u662F\u5426\u7B80\u6D01\n\n2. **\u4EE3\u7801\u8D28\u91CF**\n - \u4EE3\u7801\u662F\u5426\u6613\u4E8E\u7406\u89E3\n - \u662F\u5426\u6709\u91CD\u590D\u4EE3\u7801\n - \u6027\u80FD\u662F\u5426\u6709\u95EE\u9898\n\n3. **TSX \u89C4\u8303**\n - \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u800C\u975E\u4E09\u5143\u8868\u8FBE\u5F0F\n - \u4F7F\u7528\u53EF\u9009\u94FE\u8BBF\u95EE\u5BF9\u8C61\u5C5E\u6027\n - \u5217\u8868\u6E32\u67D3\u662F\u5426\u6709 key\n\n## \u8F93\u51FA\u683C\u5F0F\n\n\u63D0\u4F9B\u8BE6\u7EC6\u7684\u5BA1\u67E5\u62A5\u544A\uFF0C\u5305\u62EC\uFF1A\n- \u53D1\u73B0\u7684\u95EE\u9898\n- \u6539\u8FDB\u5EFA\u8BAE\n- \u4F18\u5148\u7EA7\u8BC4\u4F30\n");
49187
+ files.push(reviewTsxPath);
49188
+ createPagePath = path__namespace.join(commandsDir, 'create-page.md');
49189
+ fs__namespace.writeFileSync(createPagePath, "# \u521B\u5EFA\u65B0\u9875\u9762\n\n\u521B\u5EFA\u7B26\u5408 Appthen \u89C4\u8303\u7684\u65B0\u9875\u9762\u3002\n\n## \u91CD\u8981\u63D0\u793A\n\n\u26A0\uFE0F **\u5728\u751F\u6210\u4EE3\u7801\u524D\uFF0C\u5FC5\u987B\uFF1A**\n\n1. \u9605\u8BFB `.appthen/prompts/tsx-generation.md`\n2. \u68C0\u67E5 `.appthen/prompts/decision-tree.md` \u4E2D\u7684\u51B3\u7B56\u6D41\u7A0B\n3. \u786E\u8BA4\u7406\u89E3\u6240\u6709\u7EA6\u675F\u548C\u9650\u5236\n\n## \u751F\u6210\u6B65\u9AA4\n\n1. **\u786E\u8BA4\u9700\u6C42**\n - \u9875\u9762\u540D\u79F0\u548C\u8DEF\u7531\n - \u9700\u8981\u7684\u529F\u80FD\n - \u6570\u636E\u6765\u6E90\uFF08API \u63A5\u53E3\uFF09\n\n2. **\u751F\u6210\u4EE3\u7801**\n - \u5305\u542B\u5B8C\u6574\u7684\u6587\u4EF6\u7ED3\u6784\n - \u9075\u5B88\u6240\u6709 TSX \u89C4\u8303\n - \u4F7F\u7528\u6B63\u786E\u7684\u5143\u6570\u636E\u6CE8\u91CA\n\n3. **\u9A8C\u8BC1\u4EE3\u7801**\n - \u8FD0\u884C `appthen check-tsx -f \"path/to/page.tsx\"`\n - \u4FEE\u6B63\u6240\u6709\u9519\u8BEF\n\n4. **\u6D4B\u8BD5\u529F\u80FD**\n - \u5728\u4F4E\u4EE3\u7801\u7CFB\u7EDF\u4E2D\u5BFC\u5165\n - \u6D4B\u8BD5\u6240\u6709\u529F\u80FD\n\n## \u6A21\u677F\u53C2\u8003\n\n\u53C2\u8003 `.appthen/prompts/tsx-generation.md` \u4E2D\u7684\u5B8C\u6574\u793A\u4F8B\u3002\n");
49190
+ files.push(createPagePath);
49191
+ createComponentPath = path__namespace.join(commandsDir, 'create-component.md');
49192
+ fs__namespace.writeFileSync(createComponentPath, "# \u521B\u5EFA\u65B0\u7EC4\u4EF6\n\n\u521B\u5EFA\u7B26\u5408 Appthen \u89C4\u8303\u7684\u65B0\u7EC4\u4EF6\u3002\n\n## \u91CD\u8981\u63D0\u793A\n\n\u26A0\uFE0F **\u5728\u751F\u6210\u4EE3\u7801\u524D\uFF0C\u5FC5\u987B\uFF1A**\n\n1. \u9605\u8BFB `.appthen/prompts/tsx-generation.md`\n2. \u68C0\u67E5 `.appthen/prompts/decision-tree.md` \u4E2D\u7684\u51B3\u7B56\u6D41\u7A0B\n3. \u786E\u8BA4\u7406\u89E3\u6240\u6709\u7EA6\u675F\u548C\u9650\u5236\n\n## \u751F\u6210\u6B65\u9AA4\n\n1. **\u786E\u8BA4\u9700\u6C42**\n - \u7EC4\u4EF6\u540D\u79F0\u548C\u7528\u9014\n - Props \u5B9A\u4E49\n - State \u5B9A\u4E49\uFF08\u5982\u679C\u9700\u8981\uFF09\n\n2. **\u751F\u6210\u4EE3\u7801**\n - \u5305\u542B\u5B8C\u6574\u7684\u6587\u4EF6\u7ED3\u6784\n - \u9075\u5B88\u6240\u6709 TSX \u89C4\u8303\n - \u4F7F\u7528 @type Component \u5143\u6570\u636E\n\n3. **\u9A8C\u8BC1\u4EE3\u7801**\n - \u8FD0\u884C `appthen check-tsx -f \"path/to/component.tsx\"`\n - \u4FEE\u6B63\u6240\u6709\u9519\u8BEF\n\n4. **\u6D4B\u8BD5\u529F\u80FD**\n - \u5728\u9875\u9762\u4E2D\u4F7F\u7528\u7EC4\u4EF6\n - \u6D4B\u8BD5\u6240\u6709 Props \u548C\u4EA4\u4E92\n\n## \u7EC4\u4EF6 vs \u9875\u9762\n\n- **\u9875\u9762**\uFF1A\u4F7F\u7528 @type Page\uFF0C\u53EF\u4EE5\u901A\u8FC7 URL \u8BBF\u95EE\n- **\u7EC4\u4EF6**\uFF1A\u4F7F\u7528 @type Component\uFF0C\u53EF\u590D\u7528\u7684 UI \u5355\u5143\n\n## \u6A21\u677F\u53C2\u8003\n\n\u53C2\u8003 `.appthen/prompts/tsx-generation.md` \u4E2D\u7684\u5B8C\u6574\u793A\u4F8B\u3002\n");
49193
+ files.push(createComponentPath);
49194
+ if (this.verbose) {
49195
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u81EA\u5B9A\u4E49\u547D\u4EE4: ".concat(files.length, " \u4E2A\u6587\u4EF6"));
49196
+ }
49197
+ return [2 /*return*/, files];
49198
+ });
49199
+ });
49200
+ };
49201
+ return ClaudeCodeGenerator;
49202
+ }());
49203
+
49204
+ /**
49205
+ * Cursor 生成器
49206
+ * 生成 Cursor 特定的配置文件
49207
+ */
49208
+ var CursorGenerator = /** @class */ (function () {
49209
+ function CursorGenerator(cwd, config, verbose) {
49210
+ this.cwd = cwd;
49211
+ this.config = config;
49212
+ this.verbose = verbose;
49213
+ }
49214
+ /**
49215
+ * 生成 Cursor 配置
49216
+ */
49217
+ CursorGenerator.prototype.generate = function () {
49218
+ return __awaiter(this, void 0, void 0, function () {
49219
+ var files, cursorDir, rulesFile, promptsDir, instructionsFile, error_1;
49220
+ return __generator(this, function (_a) {
49221
+ switch (_a.label) {
49222
+ case 0:
49223
+ files = [];
49224
+ _a.label = 1;
49225
+ case 1:
49226
+ _a.trys.push([1, 4, , 5]);
49227
+ if (this.verbose) {
49228
+ console.log('🎯 配置 Cursor 集成...');
49229
+ }
49230
+ cursorDir = path__namespace.join(this.cwd, '.cursor');
49231
+ if (!fs__namespace.existsSync(cursorDir)) {
49232
+ fs__namespace.mkdirSync(cursorDir, { recursive: true });
49233
+ if (this.verbose) {
49234
+ console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(cursorDir));
49235
+ }
49236
+ }
49237
+ return [4 /*yield*/, this.createRulesFile(cursorDir)];
49238
+ case 2:
49239
+ rulesFile = _a.sent();
49240
+ files.push(rulesFile);
49241
+ promptsDir = path__namespace.join(cursorDir, 'prompts');
49242
+ if (!fs__namespace.existsSync(promptsDir)) {
49243
+ fs__namespace.mkdirSync(promptsDir, { recursive: true });
49244
+ }
49245
+ return [4 /*yield*/, this.createCustomInstructions(promptsDir)];
49246
+ case 3:
49247
+ instructionsFile = _a.sent();
49248
+ files.push(instructionsFile);
49249
+ if (this.verbose) {
49250
+ console.log('✅ Cursor 配置完成');
49251
+ }
49252
+ return [2 /*return*/, {
49253
+ success: true,
49254
+ files: files,
49255
+ message: 'Cursor configuration created successfully',
49256
+ }];
49257
+ case 4:
49258
+ error_1 = _a.sent();
49259
+ return [2 /*return*/, {
49260
+ success: false,
49261
+ files: [],
49262
+ error: error_1.message,
49263
+ }];
49264
+ case 5: return [2 /*return*/];
49265
+ }
49266
+ });
49267
+ });
49268
+ };
49269
+ /**
49270
+ * 创建 Cursor Rules 文件
49271
+ */
49272
+ CursorGenerator.prototype.createRulesFile = function (cursorDir) {
49273
+ return __awaiter(this, void 0, void 0, function () {
49274
+ var rulesPath, rulesContent;
49275
+ return __generator(this, function (_a) {
49276
+ rulesPath = path__namespace.join(cursorDir, 'rules.md');
49277
+ rulesContent = "# Cursor Rules for ".concat(this.config.projectName, "\n\n## TSX \u4EE3\u7801\u751F\u6210\u89C4\u8303\n\n### \u6587\u4EF6\u7ED3\u6784\u8981\u6C42\n\n\u6240\u6709 TSX \u6587\u4EF6\u5FC5\u987B\u9075\u5FAA\u4EE5\u4E0B\u7ED3\u6784\uFF1A\n\n```typescript\n/**\n * @type Page|Component\n * @description \u7EC4\u4EF6\u63CF\u8FF0\n */\n\nimport React from 'react';\n\nclass IProps {\n // Props \u5B9A\u4E49\n}\n\nclass IState {\n // State \u5B9A\u4E49\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n return (\n // JSX\n );\n }\n}\n\nexport default Document;\n```\n\n### \u5173\u952E\u89C4\u5219\n\n1. **\u5FC5\u987B\u5305\u542B JSDoc \u5143\u6570\u636E**\n - \u4F7F\u7528 `@type Page` \u6216 `@type Component`\n - \u4F7F\u7528 `@description` \u63CF\u8FF0\u7EC4\u4EF6\u7528\u9014\n\n2. **\u4F7F\u7528 class \u5B9A\u4E49\u63A5\u53E3**\n - Props: `class IProps { }`\n - State: `class IState { }`\n\n3. **render() \u65B9\u6CD5\u89C4\u8303**\n - \u53EA\u5305\u542B `return` \u8BED\u53E5\u548C JSX\n - \u4E0D\u5305\u542B\u590D\u6742\u903B\u8F91\n - \u590D\u6742\u903B\u8F91\u63D0\u53D6\u5230\u5355\u72EC\u65B9\u6CD5\n\n4. **\u6761\u4EF6\u6E32\u67D3**\n - \u2705 \u4F7F\u7528: `{condition && <Component />}`\n - \u274C \u907F\u514D: `{condition ? <A /> : <B />}`\n\n5. **\u53EF\u9009\u94FE**\n - \u2705 \u4F7F\u7528: `user?.profile?.name`\n - \u274C \u907F\u514D: `user.profile.name`\n\n6. **\u7C7B\u578B\u6CE8\u89E3**\n - \u274C \u4E0D\u8981\u5728\u65B9\u6CD5\u53C2\u6570\u4E2D\u4F7F\u7528 TypeScript \u7C7B\u578B\u6CE8\u89E3\n - \u7C7B\u578B\u4FE1\u606F\u5E94\u8BE5\u5728 IProps \u548C IState \u4E2D\u5B9A\u4E49\n\n### \u4EE3\u7801\u793A\u4F8B\n\n```typescript\n/**\n * @type Page\n * @description \u7528\u6237\u5217\u8868\u9875\u9762\n */\n\nimport React from 'react';\n\nclass IProps {\n users: Array<{ id: string; name: string }>;\n onUserClick: (userId: string) => void;\n}\n\nclass IState {\n loading: boolean;\n searchText: string;\n}\n\nclass Document extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props);\n this.state = {\n loading: false,\n searchText: '',\n };\n }\n\n getFilteredUsers() {\n const { users } = this.props;\n const { searchText } = this.state;\n \n if (!searchText) return users;\n \n return users.filter(u =>\n u?.name?.toLowerCase().includes(searchText.toLowerCase())\n );\n }\n\n render() {\n const { onUserClick } = this.props;\n const { loading, searchText } = this.state;\n const filteredUsers = this.getFilteredUsers();\n\n return (\n <div>\n <input\n value={searchText}\n onChange={(e) => this.setState({ searchText: e.target.value })}\n />\n \n {loading && <div>\u52A0\u8F7D\u4E2D...</div>}\n \n {!loading && filteredUsers.length === 0 && (\n <div>\u6682\u65E0\u6570\u636E</div>\n )}\n \n {!loading && filteredUsers.length > 0 && (\n <ul>\n {filteredUsers.map(user => (\n <li key={user.id} onClick={() => onUserClick(user.id)}>\n {user?.name}\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u9879\u76EE\u7279\u5B9A\u89C4\u5219\n\n- \u9879\u76EE\u540D\u79F0: ").concat(this.config.projectName, "\n- \u7A7A\u95F4ID: ").concat(this.config.spaceId, "\n- \u521B\u5EFA\u65F6\u95F4: ").concat(this.config.createdAt, "\n\n## \u66F4\u591A\u4FE1\u606F\n\n\u8BE6\u7EC6\u7684\u63D0\u793A\u8BCD\u548C\u89C4\u8303\u8BF7\u67E5\u770B `.appthen/prompts/` \u76EE\u5F55\u3002\n");
49278
+ fs__namespace.writeFileSync(rulesPath, rulesContent);
49279
+ if (this.verbose) {
49280
+ console.log("\uD83D\uDCDD \u521B\u5EFA Cursor Rules: ".concat(rulesPath));
49281
+ }
49282
+ return [2 /*return*/, rulesPath];
49283
+ });
49284
+ });
49285
+ };
49286
+ /**
49287
+ * 创建自定义指令文件
49288
+ */
49289
+ CursorGenerator.prototype.createCustomInstructions = function (promptsDir) {
49290
+ return __awaiter(this, void 0, void 0, function () {
49291
+ var instructionsPath, instructionsContent;
49292
+ return __generator(this, function (_a) {
49293
+ instructionsPath = path__namespace.join(promptsDir, 'custom-instructions.md');
49294
+ instructionsContent = "# Custom Instructions for ".concat(this.config.projectName, "\n\n## \u4EE3\u7801\u751F\u6210\u6307\u4EE4\n\n\u5F53\u751F\u6210 TSX \u4EE3\u7801\u65F6\uFF1A\n\n1. \u59CB\u7EC8\u9075\u5FAA `.cursor/rules.md` \u4E2D\u5B9A\u4E49\u7684\u89C4\u8303\n2. \u786E\u4FDD\u5305\u542B\u5B8C\u6574\u7684 JSDoc \u5143\u6570\u636E\n3. \u4F7F\u7528 class \u5B9A\u4E49 IProps \u548C IState\n4. render() \u65B9\u6CD5\u4FDD\u6301\u7B80\u6D01\n5. \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u8FDB\u884C\u6761\u4EF6\u6E32\u67D3\n6. \u4F7F\u7528\u53EF\u9009\u94FE\u8BBF\u95EE\u5BF9\u8C61\u5C5E\u6027\n\n## \u4EE3\u7801\u5BA1\u67E5\u6307\u4EE4\n\n\u5F53\u5BA1\u67E5\u4EE3\u7801\u65F6\uFF1A\n\n1. \u68C0\u67E5\u662F\u5426\u7B26\u5408 TSX \u89C4\u8303\n2. \u8BC6\u522B\u6F5C\u5728\u7684\u6027\u80FD\u95EE\u9898\n3. \u68C0\u67E5\u8FB9\u754C\u60C5\u51B5\u5904\u7406\n4. \u9A8C\u8BC1\u9519\u8BEF\u5904\u7406\u903B\u8F91\n5. \u8BC4\u4F30\u4EE3\u7801\u53EF\u7EF4\u62A4\u6027\n\n## \u91CD\u6784\u6307\u4EE4\n\n\u5F53\u91CD\u6784\u4EE3\u7801\u65F6\uFF1A\n\n1. \u4FDD\u6301\u529F\u80FD\u4E0D\u53D8\n2. \u63D0\u53D6\u91CD\u590D\u4EE3\u7801\n3. \u7B80\u5316\u590D\u6742\u903B\u8F91\n4. \u63D0\u9AD8\u4EE3\u7801\u53EF\u8BFB\u6027\n5. \u4F18\u5316\u6027\u80FD\n\n## \u53C2\u8003\u8D44\u6599\n\n- TSX \u751F\u6210\u89C4\u8303: `.appthen/prompts/tsx-generation.md`\n- \u4EE3\u7801\u5BA1\u67E5\u6307\u5357: `.appthen/prompts/code-review.md`\n- \u91CD\u6784\u6307\u5357: `.appthen/prompts/refactoring.md`\n");
49295
+ fs__namespace.writeFileSync(instructionsPath, instructionsContent);
49296
+ if (this.verbose) {
49297
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u81EA\u5B9A\u4E49\u6307\u4EE4: ".concat(instructionsPath));
49298
+ }
49299
+ return [2 /*return*/, instructionsPath];
49300
+ });
49301
+ });
49302
+ };
49303
+ return CursorGenerator;
49304
+ }());
49305
+
49306
+ /**
49307
+ * Windsurf 生成器
49308
+ * 生成 Windsurf (Codeium) 特定的配置文件
49309
+ */
49310
+ var WindsurfGenerator = /** @class */ (function () {
49311
+ function WindsurfGenerator(cwd, config, verbose) {
49312
+ this.cwd = cwd;
49313
+ this.config = config;
49314
+ this.verbose = verbose;
49315
+ }
49316
+ /**
49317
+ * 生成 Windsurf 配置
49318
+ */
49319
+ WindsurfGenerator.prototype.generate = function () {
49320
+ return __awaiter(this, void 0, void 0, function () {
49321
+ var files, windsurfDir, cascadeFile, rulesFile, error_1;
49322
+ return __generator(this, function (_a) {
49323
+ switch (_a.label) {
49324
+ case 0:
49325
+ files = [];
49326
+ _a.label = 1;
49327
+ case 1:
49328
+ _a.trys.push([1, 4, , 5]);
49329
+ if (this.verbose) {
49330
+ console.log('🌊 配置 Windsurf 集成...');
49331
+ }
49332
+ windsurfDir = path__namespace.join(this.cwd, '.windsurf');
49333
+ if (!fs__namespace.existsSync(windsurfDir)) {
49334
+ fs__namespace.mkdirSync(windsurfDir, { recursive: true });
49335
+ if (this.verbose) {
49336
+ console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(windsurfDir));
49337
+ }
49338
+ }
49339
+ return [4 /*yield*/, this.createCascadeConfig(windsurfDir)];
49340
+ case 2:
49341
+ cascadeFile = _a.sent();
49342
+ files.push(cascadeFile);
49343
+ return [4 /*yield*/, this.createRulesFile(windsurfDir)];
49344
+ case 3:
49345
+ rulesFile = _a.sent();
49346
+ files.push(rulesFile);
49347
+ if (this.verbose) {
49348
+ console.log('✅ Windsurf 配置完成');
49349
+ }
49350
+ return [2 /*return*/, {
49351
+ success: true,
49352
+ files: files,
49353
+ message: 'Windsurf configuration created successfully',
49354
+ }];
49355
+ case 4:
49356
+ error_1 = _a.sent();
49357
+ return [2 /*return*/, {
49358
+ success: false,
49359
+ files: [],
49360
+ error: error_1.message,
49361
+ }];
49362
+ case 5: return [2 /*return*/];
49363
+ }
49364
+ });
49365
+ });
49366
+ };
49367
+ /**
49368
+ * 创建 Cascade 配置文件
49369
+ */
49370
+ WindsurfGenerator.prototype.createCascadeConfig = function (windsurfDir) {
49371
+ return __awaiter(this, void 0, void 0, function () {
49372
+ var cascadePath, cascadeConfig;
49373
+ return __generator(this, function (_a) {
49374
+ cascadePath = path__namespace.join(windsurfDir, 'cascade.json');
49375
+ cascadeConfig = {
49376
+ name: this.config.projectName,
49377
+ description: "Agent+ Space configuration for ".concat(this.config.projectName),
49378
+ version: '1.0.0',
49379
+ rules: {
49380
+ tsx: {
49381
+ enabled: true,
49382
+ strictMode: true,
49383
+ checkMetadata: true,
49384
+ checkClassDefinitions: true,
49385
+ checkRenderMethod: true,
49386
+ enforceConditionalRendering: true,
49387
+ enforceOptionalChaining: true,
49388
+ },
49389
+ },
49390
+ prompts: {
49391
+ codeGeneration: '.appthen/prompts/tsx-generation.md',
49392
+ codeReview: '.appthen/prompts/code-review.md',
49393
+ refactoring: '.appthen/prompts/refactoring.md',
49394
+ },
49395
+ workspace: {
49396
+ root: this.cwd,
49397
+ include: ['src/**/*', 'docs/**/*'],
49398
+ exclude: [
49399
+ 'node_modules/**',
49400
+ 'dist/**',
49401
+ 'build/**',
49402
+ '.git/**',
49403
+ '*.log',
49404
+ ],
49405
+ },
49406
+ };
49407
+ fs__namespace.writeFileSync(cascadePath, JSON.stringify(cascadeConfig, null, 2));
49408
+ if (this.verbose) {
49409
+ console.log("\uD83D\uDCDD \u521B\u5EFA Cascade \u914D\u7F6E: ".concat(cascadePath));
49410
+ }
49411
+ return [2 /*return*/, cascadePath];
49412
+ });
49413
+ });
49414
+ };
49415
+ /**
49416
+ * 创建 Rules 文件
49417
+ */
49418
+ WindsurfGenerator.prototype.createRulesFile = function (windsurfDir) {
49419
+ return __awaiter(this, void 0, void 0, function () {
49420
+ var rulesPath, rulesContent;
49421
+ return __generator(this, function (_a) {
49422
+ rulesPath = path__namespace.join(windsurfDir, 'rules.md');
49423
+ rulesContent = "# Windsurf Rules for ".concat(this.config.projectName, "\n\n## TSX \u4EE3\u7801\u89C4\u8303\n\n### \u57FA\u672C\u8981\u6C42\n\n1. **\u6587\u4EF6\u7ED3\u6784**\n - JSDoc \u5143\u6570\u636E\u6CE8\u91CA\uFF08@type, @description\uFF09\n - class IProps \u548C class IState \u5B9A\u4E49\n - class Document extends React.Component\n - render() \u65B9\u6CD5\u53EA\u5305\u542B return \u8BED\u53E5\n\n2. **\u6761\u4EF6\u6E32\u67D3**\n - \u4F7F\u7528 && \u8FD0\u7B97\u7B26\n - \u907F\u514D\u4E09\u5143\u8868\u8FBE\u5F0F\n\n3. **\u5BF9\u8C61\u8BBF\u95EE**\n - \u4F7F\u7528\u53EF\u9009\u94FE\uFF08?.\uFF09\n - \u907F\u514D\u76F4\u63A5\u5C5E\u6027\u8BBF\u95EE\n\n### \u4EE3\u7801\u751F\u6210\u6A21\u677F\n\n```typescript\n/**\n * @type Page|Component\n * @description [\u63CF\u8FF0]\n */\n\nimport React from 'react';\n\nclass IProps {\n // Props \u5B9A\u4E49\n}\n\nclass IState {\n // State \u5B9A\u4E49\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n return (\n // JSX\n );\n }\n}\n\nexport default Document;\n```\n\n### \u6700\u4F73\u5B9E\u8DF5\n\n- \u4FDD\u6301 render() \u65B9\u6CD5\u7B80\u6D01\n- \u590D\u6742\u903B\u8F91\u63D0\u53D6\u5230\u5355\u72EC\u65B9\u6CD5\n- \u4F7F\u7528\u6709\u610F\u4E49\u7684\u53D8\u91CF\u540D\n- \u6DFB\u52A0\u5FC5\u8981\u7684\u6CE8\u91CA\n- \u5904\u7406\u8FB9\u754C\u60C5\u51B5\n\n### \u53C2\u8003\u8D44\u6599\n\n\u8BE6\u7EC6\u89C4\u8303\u8BF7\u67E5\u770B\uFF1A\n- `.appthen/prompts/tsx-generation.md`\n- `.appthen/prompts/code-review.md`\n- `.appthen/prompts/refactoring.md`\n\n## \u9879\u76EE\u4FE1\u606F\n\n- \u9879\u76EE: ").concat(this.config.projectName, "\n- \u7A7A\u95F4ID: ").concat(this.config.spaceId, "\n- \u5DE5\u5177: Windsurf (Codeium)\n");
49424
+ fs__namespace.writeFileSync(rulesPath, rulesContent);
49425
+ if (this.verbose) {
49426
+ console.log("\uD83D\uDCDD \u521B\u5EFA Rules \u6587\u4EF6: ".concat(rulesPath));
49427
+ }
49428
+ return [2 /*return*/, rulesPath];
49429
+ });
49430
+ });
49431
+ };
49432
+ return WindsurfGenerator;
49433
+ }());
49434
+
49435
+ /**
49436
+ * 阿里云 Coder 生成器
49437
+ * 生成阿里云 Coder 特定的配置文件
49438
+ */
49439
+ var CoderGenerator = /** @class */ (function () {
49440
+ function CoderGenerator(cwd, config, verbose) {
49441
+ this.cwd = cwd;
49442
+ this.config = config;
49443
+ this.verbose = verbose;
49444
+ }
49445
+ /**
49446
+ * 生成阿里云 Coder 配置
49447
+ */
49448
+ CoderGenerator.prototype.generate = function () {
49449
+ return __awaiter(this, void 0, void 0, function () {
49450
+ var files, coderDir, configFile, templatesDir, templateFile, error_1;
49451
+ return __generator(this, function (_a) {
49452
+ switch (_a.label) {
49453
+ case 0:
49454
+ files = [];
49455
+ _a.label = 1;
49456
+ case 1:
49457
+ _a.trys.push([1, 4, , 5]);
49458
+ if (this.verbose) {
49459
+ console.log('☁️ 配置阿里云 Coder 集成...');
49460
+ }
49461
+ coderDir = path__namespace.join(this.cwd, '.coder');
49462
+ if (!fs__namespace.existsSync(coderDir)) {
49463
+ fs__namespace.mkdirSync(coderDir, { recursive: true });
49464
+ if (this.verbose) {
49465
+ console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(coderDir));
49466
+ }
49467
+ }
49468
+ return [4 /*yield*/, this.createConfig(coderDir)];
49469
+ case 2:
49470
+ configFile = _a.sent();
49471
+ files.push(configFile);
49472
+ templatesDir = path__namespace.join(coderDir, 'templates');
49473
+ if (!fs__namespace.existsSync(templatesDir)) {
49474
+ fs__namespace.mkdirSync(templatesDir, { recursive: true });
49475
+ }
49476
+ return [4 /*yield*/, this.createTsxTemplate(templatesDir)];
49477
+ case 3:
49478
+ templateFile = _a.sent();
49479
+ files.push(templateFile);
49480
+ if (this.verbose) {
49481
+ console.log('✅ 阿里云 Coder 配置完成');
49482
+ }
49483
+ return [2 /*return*/, {
49484
+ success: true,
49485
+ files: files,
49486
+ message: 'Coder configuration created successfully',
49487
+ }];
49488
+ case 4:
49489
+ error_1 = _a.sent();
49490
+ return [2 /*return*/, {
49491
+ success: false,
49492
+ files: [],
49493
+ error: error_1.message,
49494
+ }];
49495
+ case 5: return [2 /*return*/];
49496
+ }
49497
+ });
49498
+ });
49499
+ };
49500
+ /**
49501
+ * 创建配置文件
49502
+ */
49503
+ CoderGenerator.prototype.createConfig = function (coderDir) {
49504
+ return __awaiter(this, void 0, void 0, function () {
49505
+ var configPath, config;
49506
+ return __generator(this, function (_a) {
49507
+ configPath = path__namespace.join(coderDir, 'config.json');
49508
+ config = {
49509
+ projectName: this.config.projectName,
49510
+ spaceId: this.config.spaceId,
49511
+ version: '1.0.0',
49512
+ codeGeneration: {
49513
+ tsx: {
49514
+ enabled: true,
49515
+ template: 'templates/tsx-template.md',
49516
+ rules: {
49517
+ requireMetadata: true,
49518
+ requireClassDefinitions: true,
49519
+ enforceRenderStructure: true,
49520
+ useConditionalOperator: true,
49521
+ useOptionalChaining: true,
49522
+ },
49523
+ },
49524
+ },
49525
+ prompts: {
49526
+ generation: '../.appthen/prompts/tsx-generation.md',
49527
+ review: '../.appthen/prompts/code-review.md',
49528
+ refactoring: '../.appthen/prompts/refactoring.md',
49529
+ },
49530
+ workspace: {
49531
+ include: ['src/**/*', 'docs/**/*'],
49532
+ exclude: [
49533
+ 'node_modules/**',
49534
+ 'dist/**',
49535
+ 'build/**',
49536
+ '.git/**',
49537
+ '*.log',
49538
+ ],
49539
+ },
49540
+ };
49541
+ fs__namespace.writeFileSync(configPath, JSON.stringify(config, null, 2));
49542
+ if (this.verbose) {
49543
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
49544
+ }
49545
+ return [2 /*return*/, configPath];
49546
+ });
49547
+ });
49548
+ };
49549
+ /**
49550
+ * 创建 TSX 模板
49551
+ */
49552
+ CoderGenerator.prototype.createTsxTemplate = function (templatesDir) {
49553
+ return __awaiter(this, void 0, void 0, function () {
49554
+ var templatePath, templateContent;
49555
+ return __generator(this, function (_a) {
49556
+ templatePath = path__namespace.join(templatesDir, 'tsx-template.md');
49557
+ templateContent = "# TSX \u4EE3\u7801\u6A21\u677F - ".concat(this.config.projectName, "\n\n## \u57FA\u7840\u6A21\u677F\n\n```typescript\n/**\n * @type [Page|Component]\n * @description [\u7EC4\u4EF6\u63CF\u8FF0]\n */\n\nimport React from 'react';\n\nclass IProps {\n // TODO: \u5B9A\u4E49 Props\n}\n\nclass IState {\n // TODO: \u5B9A\u4E49 State\n}\n\nclass Document extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props);\n this.state = {\n // TODO: \u521D\u59CB\u5316 State\n };\n }\n\n render() {\n return (\n <div>\n {/* TODO: \u5B9E\u73B0 JSX */}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u9875\u9762\u6A21\u677F\n\n```typescript\n/**\n * @type Page\n * @description [\u9875\u9762\u63CF\u8FF0]\n */\n\nimport React from 'react';\n\nclass IProps {\n // \u9875\u9762 Props\n}\n\nclass IState {\n loading: boolean;\n data: any;\n error: string | null;\n}\n\nclass Document extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props);\n this.state = {\n loading: false,\n data: null,\n error: null,\n };\n }\n\n componentDidMount() {\n this.loadData();\n }\n\n async loadData() {\n this.setState({ loading: true, error: null });\n \n try {\n // TODO: \u52A0\u8F7D\u6570\u636E\n const data = await fetchData();\n this.setState({ data, loading: false });\n } catch (error) {\n this.setState({ error: error.message, loading: false });\n }\n }\n\n render() {\n const { loading, data, error } = this.state;\n\n return (\n <div className=\"page\">\n {loading && <div>\u52A0\u8F7D\u4E2D...</div>}\n \n {error && <div className=\"error\">{error}</div>}\n \n {!loading && !error && data && (\n <div className=\"content\">\n {/* TODO: \u6E32\u67D3\u6570\u636E */}\n </div>\n )}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u7EC4\u4EF6\u6A21\u677F\n\n```typescript\n/**\n * @type Component\n * @description [\u7EC4\u4EF6\u63CF\u8FF0]\n */\n\nimport React from 'react';\n\nclass IProps {\n // \u7EC4\u4EF6 Props\n}\n\nclass IState {\n // \u7EC4\u4EF6 State\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n const { } = this.props;\n \n return (\n <div className=\"component\">\n {/* TODO: \u5B9E\u73B0\u7EC4\u4EF6 */}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u4F7F\u7528\u8BF4\u660E\n\n1. \u9009\u62E9\u5408\u9002\u7684\u6A21\u677F\uFF08\u57FA\u7840/\u9875\u9762/\u7EC4\u4EF6\uFF09\n2. \u66FF\u6362 TODO \u6CE8\u91CA\u4E2D\u7684\u5185\u5BB9\n3. \u786E\u4FDD\u9075\u5FAA TSX \u89C4\u8303\uFF1A\n - \u5305\u542B JSDoc \u5143\u6570\u636E\n - \u4F7F\u7528 class \u5B9A\u4E49 IProps \u548C IState\n - render() \u53EA\u5305\u542B return \u8BED\u53E5\n - \u4F7F\u7528 && \u8FD0\u7B97\u7B26\u8FDB\u884C\u6761\u4EF6\u6E32\u67D3\n - \u4F7F\u7528\u53EF\u9009\u94FE\u8BBF\u95EE\u5BF9\u8C61\u5C5E\u6027\n\n## \u53C2\u8003\u8D44\u6599\n\n- \u8BE6\u7EC6\u89C4\u8303: `.appthen/prompts/tsx-generation.md`\n- \u4EE3\u7801\u5BA1\u67E5: `.appthen/prompts/code-review.md`\n- \u91CD\u6784\u6307\u5357: `.appthen/prompts/refactoring.md`\n");
49558
+ fs__namespace.writeFileSync(templatePath, templateContent);
49559
+ if (this.verbose) {
49560
+ console.log("\uD83D\uDCDD \u521B\u5EFA TSX \u6A21\u677F: ".concat(templatePath));
49561
+ }
49562
+ return [2 /*return*/, templatePath];
49563
+ });
49564
+ });
49565
+ };
49566
+ return CoderGenerator;
49567
+ }());
49568
+
49569
+ /**
49570
+ * Augment 生成器
49571
+ * 生成 Augment (VSCode 插件) 特定的配置文件
49572
+ */
49573
+ var AugmentGenerator = /** @class */ (function () {
49574
+ function AugmentGenerator(cwd, config, verbose) {
49575
+ this.cwd = cwd;
49576
+ this.config = config;
49577
+ this.verbose = verbose;
49578
+ }
49579
+ /**
49580
+ * 生成 Augment 配置
49581
+ */
49582
+ AugmentGenerator.prototype.generate = function () {
49583
+ return __awaiter(this, void 0, void 0, function () {
49584
+ var files, augmentDir, configFile, contextDir, contextFile, error_1;
49585
+ return __generator(this, function (_a) {
49586
+ switch (_a.label) {
49587
+ case 0:
49588
+ files = [];
49589
+ _a.label = 1;
49590
+ case 1:
49591
+ _a.trys.push([1, 4, , 5]);
49592
+ if (this.verbose) {
49593
+ console.log('🔧 配置 Augment 集成...');
49594
+ }
49595
+ augmentDir = path__namespace.join(this.cwd, '.augment');
49596
+ if (!fs__namespace.existsSync(augmentDir)) {
49597
+ fs__namespace.mkdirSync(augmentDir, { recursive: true });
49598
+ if (this.verbose) {
49599
+ console.log("\uD83D\uDCC1 \u521B\u5EFA\u76EE\u5F55: ".concat(augmentDir));
49600
+ }
49601
+ }
49602
+ return [4 /*yield*/, this.createConfig(augmentDir)];
49603
+ case 2:
49604
+ configFile = _a.sent();
49605
+ files.push(configFile);
49606
+ contextDir = path__namespace.join(augmentDir, 'context');
49607
+ if (!fs__namespace.existsSync(contextDir)) {
49608
+ fs__namespace.mkdirSync(contextDir, { recursive: true });
49609
+ }
49610
+ return [4 /*yield*/, this.createProjectContext(contextDir)];
49611
+ case 3:
49612
+ contextFile = _a.sent();
49613
+ files.push(contextFile);
49614
+ if (this.verbose) {
49615
+ console.log('✅ Augment 配置完成');
49616
+ }
49617
+ return [2 /*return*/, {
49618
+ success: true,
49619
+ files: files,
49620
+ message: 'Augment configuration created successfully',
49621
+ }];
49622
+ case 4:
49623
+ error_1 = _a.sent();
49624
+ return [2 /*return*/, {
49625
+ success: false,
49626
+ files: [],
49627
+ error: error_1.message,
49628
+ }];
49629
+ case 5: return [2 /*return*/];
49630
+ }
49631
+ });
49632
+ });
49633
+ };
49634
+ /**
49635
+ * 创建配置文件
49636
+ */
49637
+ AugmentGenerator.prototype.createConfig = function (augmentDir) {
49638
+ return __awaiter(this, void 0, void 0, function () {
49639
+ var configPath, config;
49640
+ return __generator(this, function (_a) {
49641
+ configPath = path__namespace.join(augmentDir, 'config.json');
49642
+ config = {
49643
+ projectName: this.config.projectName,
49644
+ spaceId: this.config.spaceId,
49645
+ version: '1.0.0',
49646
+ context: {
49647
+ enabled: true,
49648
+ files: ['context/project-context.md'],
49649
+ prompts: [
49650
+ '../.appthen/prompts/tsx-generation.md',
49651
+ '../.appthen/prompts/code-review.md',
49652
+ '../.appthen/prompts/refactoring.md',
49653
+ ],
49654
+ },
49655
+ codeGeneration: {
49656
+ tsx: {
49657
+ enabled: true,
49658
+ strictMode: true,
49659
+ autoFormat: true,
49660
+ },
49661
+ },
49662
+ workspace: {
49663
+ include: ['src/**/*', 'docs/**/*'],
49664
+ exclude: [
49665
+ 'node_modules/**',
49666
+ 'dist/**',
49667
+ 'build/**',
49668
+ '.git/**',
49669
+ '*.log',
49670
+ ],
49671
+ },
49672
+ };
49673
+ fs__namespace.writeFileSync(configPath, JSON.stringify(config, null, 2));
49674
+ if (this.verbose) {
49675
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
49676
+ }
49677
+ return [2 /*return*/, configPath];
49678
+ });
49679
+ });
49680
+ };
49681
+ /**
49682
+ * 创建项目上下文文件
49683
+ */
49684
+ AugmentGenerator.prototype.createProjectContext = function (contextDir) {
49685
+ return __awaiter(this, void 0, void 0, function () {
49686
+ var contextPath, contextContent;
49687
+ return __generator(this, function (_a) {
49688
+ contextPath = path__namespace.join(contextDir, 'project-context.md');
49689
+ contextContent = "# Project Context - ".concat(this.config.projectName, "\n\n## \u9879\u76EE\u4FE1\u606F\n\n- **\u9879\u76EE\u540D\u79F0**: ").concat(this.config.projectName, "\n- **\u7A7A\u95F4ID**: ").concat(this.config.spaceId, "\n- **\u521B\u5EFA\u65F6\u95F4**: ").concat(this.config.createdAt, "\n- **AI \u5DE5\u5177**: Augment (VSCode)\n\n## TSX \u4EE3\u7801\u89C4\u8303\n\n### \u6587\u4EF6\u7ED3\u6784\n\n\u6240\u6709 TSX \u6587\u4EF6\u5FC5\u987B\u9075\u5FAA\u4EE5\u4E0B\u7ED3\u6784\uFF1A\n\n```typescript\n/**\n * @type Page|Component\n * @description \u7EC4\u4EF6\u63CF\u8FF0\n */\n\nimport React from 'react';\n\nclass IProps {\n // Props \u5B9A\u4E49\n}\n\nclass IState {\n // State \u5B9A\u4E49\n}\n\nclass Document extends React.Component<IProps, IState> {\n render() {\n return (\n // JSX\n );\n }\n}\n\nexport default Document;\n```\n\n### \u5173\u952E\u89C4\u5219\n\n1. **JSDoc \u5143\u6570\u636E**\n - \u5FC5\u987B\u5305\u542B `@type` \u548C `@description`\n - `@type` \u503C\u4E3A `Page` \u6216 `Component`\n\n2. **\u7C7B\u5B9A\u4E49**\n - \u4F7F\u7528 `class IProps` \u5B9A\u4E49 Props\n - \u4F7F\u7528 `class IState` \u5B9A\u4E49 State\n - \u7EC4\u4EF6\u7C7B\u7EE7\u627F `React.Component<IProps, IState>`\n\n3. **render() \u65B9\u6CD5**\n - \u53EA\u5305\u542B `return` \u8BED\u53E5\u548C JSX\n - \u4E0D\u5305\u542B\u590D\u6742\u903B\u8F91\n - \u590D\u6742\u903B\u8F91\u63D0\u53D6\u5230\u5355\u72EC\u65B9\u6CD5\n\n4. **\u6761\u4EF6\u6E32\u67D3**\n - \u2705 \u4F7F\u7528: `{condition && <Component />}`\n - \u274C \u907F\u514D: `{condition ? <A /> : <B />}`\n\n5. **\u5BF9\u8C61\u8BBF\u95EE**\n - \u2705 \u4F7F\u7528: `user?.profile?.name`\n - \u274C \u907F\u514D: `user.profile.name`\n\n6. **\u7C7B\u578B\u6CE8\u89E3**\n - \u274C \u4E0D\u8981\u5728\u65B9\u6CD5\u53C2\u6570\u4E2D\u4F7F\u7528 TypeScript \u7C7B\u578B\u6CE8\u89E3\n - \u7C7B\u578B\u4FE1\u606F\u5728 IProps \u548C IState \u4E2D\u5B9A\u4E49\n\n### \u4EE3\u7801\u793A\u4F8B\n\n```typescript\n/**\n * @type Page\n * @description \u7528\u6237\u5217\u8868\u9875\u9762\n */\n\nimport React from 'react';\n\nclass IProps {\n users: Array<{ id: string; name: string }>;\n}\n\nclass IState {\n loading: boolean;\n}\n\nclass Document extends React.Component<IProps, IState> {\n constructor(props: IProps) {\n super(props);\n this.state = {\n loading: false,\n };\n }\n\n render() {\n const { users } = this.props;\n const { loading } = this.state;\n\n return (\n <div>\n {loading && <div>\u52A0\u8F7D\u4E2D...</div>}\n \n {!loading && users.length === 0 && (\n <div>\u6682\u65E0\u6570\u636E</div>\n )}\n \n {!loading && users.length > 0 && (\n <ul>\n {users.map(user => (\n <li key={user.id}>{user?.name}</li>\n ))}\n </ul>\n )}\n </div>\n );\n }\n}\n\nexport default Document;\n```\n\n## \u5F00\u53D1\u5DE5\u4F5C\u6D41\n\n1. **\u4EE3\u7801\u751F\u6210**\n - \u4F7F\u7528 Augment \u751F\u6210\u7B26\u5408\u89C4\u8303\u7684 TSX \u4EE3\u7801\n - \u53C2\u8003 `.appthen/prompts/tsx-generation.md`\n\n2. **\u4EE3\u7801\u5BA1\u67E5**\n - \u68C0\u67E5\u662F\u5426\u7B26\u5408 TSX \u89C4\u8303\n - \u53C2\u8003 `.appthen/prompts/code-review.md`\n\n3. **\u4EE3\u7801\u91CD\u6784**\n - \u63D0\u53D6\u91CD\u590D\u4EE3\u7801\n - \u7B80\u5316\u590D\u6742\u903B\u8F91\n - \u53C2\u8003 `.appthen/prompts/refactoring.md`\n\n## \u53C2\u8003\u8D44\u6599\n\n- **TSX \u751F\u6210\u89C4\u8303**: `.appthen/prompts/tsx-generation.md`\n- **\u4EE3\u7801\u5BA1\u67E5\u6307\u5357**: `.appthen/prompts/code-review.md`\n- **\u91CD\u6784\u6307\u5357**: `.appthen/prompts/refactoring.md`\n\n## \u6CE8\u610F\u4E8B\u9879\n\n- \u59CB\u7EC8\u9075\u5FAA TSX \u89C4\u8303\n- \u4FDD\u6301\u4EE3\u7801\u7B80\u6D01\u6613\u8BFB\n- \u5904\u7406\u8FB9\u754C\u60C5\u51B5\n- \u6DFB\u52A0\u5FC5\u8981\u7684\u6CE8\u91CA\n- \u4F7F\u7528\u6709\u610F\u4E49\u7684\u53D8\u91CF\u540D\n");
49690
+ fs__namespace.writeFileSync(contextPath, contextContent);
49691
+ if (this.verbose) {
49692
+ console.log("\uD83D\uDCDD \u521B\u5EFA\u9879\u76EE\u4E0A\u4E0B\u6587: ".concat(contextPath));
49693
+ }
49694
+ return [2 /*return*/, contextPath];
49695
+ });
49696
+ });
49697
+ };
49698
+ return AugmentGenerator;
49699
+ }());
49700
+
49701
+ /**
49702
+ * 初始化 Agent+ Space
49703
+ */
49704
+ function initSpace(options) {
49705
+ if (options === void 0) { options = {}; }
49706
+ return __awaiter(this, void 0, void 0, function () {
49707
+ var _a, force, _b, verbose, _c, cwd, _d, skipPrompts, _e, skipHooks, configPath, tool, projectName, spaceId, spaceConfig, baseGenerator, baseResult, toolResult, allFiles, error_1;
49708
+ return __generator(this, function (_f) {
49709
+ switch (_f.label) {
49710
+ case 0:
49711
+ _a = options.force, force = _a === void 0 ? false : _a, _b = options.verbose, verbose = _b === void 0 ? false : _b, _c = options.cwd, cwd = _c === void 0 ? process.cwd() : _c, _d = options.skipPrompts, skipPrompts = _d === void 0 ? false : _d, _e = options.skipHooks, skipHooks = _e === void 0 ? false : _e;
49712
+ _f.label = 1;
49713
+ case 1:
49714
+ _f.trys.push([1, 6, , 7]);
49715
+ configPath = path__namespace.join(cwd, '.appthen/space-config.json');
49716
+ if (fs__namespace.existsSync(configPath) && !force) {
49717
+ console.log('');
49718
+ console.log('⚠️ Space 已经初始化');
49719
+ console.log(" \u914D\u7F6E\u6587\u4EF6: ".concat(configPath));
49720
+ console.log('');
49721
+ console.log('💡 提示:');
49722
+ console.log(' - 使用 --force 强制重新初始化');
49723
+ console.log(' - 使用 appthen connect 连接到编辑器');
49724
+ console.log('');
49725
+ return [2 /*return*/, { success: false, error: 'Already initialized' }];
49726
+ }
49727
+ tool = options.tool;
49728
+ if (!!tool) return [3 /*break*/, 3];
49729
+ return [4 /*yield*/, promptForTool()];
49730
+ case 2:
49731
+ tool = _f.sent();
49732
+ _f.label = 3;
49733
+ case 3:
49734
+ projectName = options.name || path__namespace.basename(cwd);
49735
+ spaceId = "".concat(projectName, "-").concat(nanoid$1(8));
49736
+ spaceConfig = {
49737
+ spaceId: spaceId,
49738
+ projectId: options.projectId,
49739
+ projectName: projectName,
49740
+ projectRoot: cwd,
49741
+ tool: tool,
49742
+ createdAt: new Date().toISOString(),
49743
+ version: '1.0.0',
49744
+ };
49745
+ console.log('');
49746
+ console.log('🚀 初始化 Agent+ Space...');
49747
+ console.log('');
49748
+ if (verbose) {
49749
+ console.log(" \u5DE5\u5177: ".concat(getToolName(tool)));
49750
+ console.log(" \u9879\u76EE: ".concat(projectName));
49751
+ console.log(" \u7A7A\u95F4ID: ".concat(spaceId));
49752
+ console.log('');
49753
+ }
49754
+ baseGenerator = new BaseGenerator(cwd, spaceConfig, verbose);
49755
+ return [4 /*yield*/, baseGenerator.generate(skipPrompts)];
49756
+ case 4:
49757
+ baseResult = _f.sent();
49758
+ if (!baseResult.success) {
49759
+ console.error('❌ 基础配置生成失败:', baseResult.error);
49760
+ return [2 /*return*/, baseResult];
49761
+ }
49762
+ return [4 /*yield*/, generateToolSpecificFiles(tool, cwd, spaceConfig, verbose, skipHooks)];
49763
+ case 5:
49764
+ toolResult = _f.sent();
49765
+ if (!toolResult.success) {
49766
+ console.error('❌ 工具配置生成失败:', toolResult.error);
49767
+ return [2 /*return*/, toolResult];
49768
+ }
49769
+ // 7. 输出成功信息
49770
+ console.log('');
49771
+ console.log('🎉 Agent+ Space 初始化完成!');
49772
+ console.log('');
49773
+ console.log('📋 已创建的文件:');
49774
+ allFiles = __spreadArray(__spreadArray([], __read(baseResult.files), false), __read(toolResult.files), false);
49775
+ allFiles.forEach(function (file) {
49776
+ var relativePath = path__namespace.relative(cwd, file);
49777
+ console.log(" \u2713 ".concat(relativePath));
49778
+ });
49779
+ console.log('');
49780
+ console.log('🚀 下一步:');
49781
+ console.log(" cd ".concat(cwd));
49782
+ console.log(' appthen connect');
49783
+ console.log('');
49784
+ console.log('📖 更多信息:');
49785
+ console.log(' - 查看 .appthen/prompts/README.md 了解提示词使用');
49786
+ if (tool === 'claude-code') {
49787
+ console.log(' - 查看 .claude/settings.json 了解 Hooks 配置');
49788
+ }
49789
+ else if (tool === 'cursor') {
49790
+ console.log(' - 查看 .cursor/rules.md 了解 Cursor Rules');
49791
+ }
49792
+ else if (tool === 'windsurf') {
49793
+ console.log(' - 查看 .windsurf/cascade.json 了解 Cascade 配置');
49794
+ }
49795
+ else if (tool === 'coder') {
49796
+ console.log(' - 查看 .coder/config.json 了解配置选项');
49797
+ }
49798
+ else if (tool === 'augment') {
49799
+ console.log(' - 查看 .augment/context/project-context.md 了解项目上下文');
49800
+ }
49801
+ console.log('');
49802
+ return [2 /*return*/, {
49803
+ success: true,
49804
+ message: 'Space initialized successfully',
49805
+ spaceId: spaceId,
49806
+ files: allFiles,
49807
+ }];
49808
+ case 6:
49809
+ error_1 = _f.sent();
49810
+ console.error('');
49811
+ console.error('❌ 初始化失败:', error_1.message);
49812
+ console.error('');
49813
+ if (verbose) {
49814
+ console.error('错误详情:', error_1);
49815
+ }
49816
+ return [2 /*return*/, {
49817
+ success: false,
49818
+ error: error_1.message,
49819
+ }];
49820
+ case 7: return [2 /*return*/];
49821
+ }
49822
+ });
49823
+ });
49824
+ }
49825
+ /**
49826
+ * 提示用户选择 AI 工具
49827
+ */
49828
+ function promptForTool() {
49829
+ return __awaiter(this, void 0, void 0, function () {
49830
+ var inquirer, answer;
49831
+ return __generator(this, function (_a) {
49832
+ switch (_a.label) {
49833
+ case 0:
49834
+ _a.trys.push([0, 3, , 4]);
49835
+ return [4 /*yield*/, Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('inquirer')); })];
49836
+ case 1:
49837
+ inquirer = _a.sent();
49838
+ return [4 /*yield*/, inquirer.default.prompt([
49839
+ {
49840
+ type: 'list',
49841
+ name: 'tool',
49842
+ message: '请选择你使用的 AI 编码工具:',
49843
+ choices: AI_TOOLS.map(function (tool) { return ({
49844
+ name: tool.name,
49845
+ value: tool.value,
49846
+ }); }),
49847
+ },
49848
+ ])];
49849
+ case 2:
49850
+ answer = _a.sent();
49851
+ return [2 /*return*/, answer.tool];
49852
+ case 3:
49853
+ _a.sent();
49854
+ // 如果 inquirer 不可用,提供友好的错误提示
49855
+ console.log('');
49856
+ console.log('⚠️ 无法启动交互式选择');
49857
+ console.log('');
49858
+ console.log('💡 请使用 --tool 参数指定 AI 工具:');
49859
+ console.log('');
49860
+ console.log(' appthen init-space --tool claude-code # Claude Code');
49861
+ console.log(' appthen init-space --tool cursor # Cursor');
49862
+ console.log(' appthen init-space --tool windsurf # Windsurf');
49863
+ console.log(' appthen init-space --tool coder # 阿里云 Coder');
49864
+ console.log(' appthen init-space --tool augment # Augment');
49865
+ console.log(' appthen init-space --tool other # 其他/跳过');
49866
+ console.log('');
49867
+ throw new Error('需要指定 --tool 参数');
49868
+ case 4: return [2 /*return*/];
49869
+ }
49870
+ });
49871
+ });
49872
+ }
49873
+ /**
49874
+ * 根据工具生成特定文件
49875
+ */
49876
+ function generateToolSpecificFiles(tool, cwd, config, verbose, skipHooks) {
49877
+ return __awaiter(this, void 0, void 0, function () {
49878
+ var _a, generator, generator, generator, generator, generator;
49879
+ return __generator(this, function (_b) {
49880
+ switch (_b.label) {
49881
+ case 0:
49882
+ _a = tool;
49883
+ switch (_a) {
49884
+ case 'claude-code': return [3 /*break*/, 1];
49885
+ case 'cursor': return [3 /*break*/, 3];
49886
+ case 'windsurf': return [3 /*break*/, 5];
49887
+ case 'coder': return [3 /*break*/, 7];
49888
+ case 'augment': return [3 /*break*/, 9];
49889
+ case 'other': return [3 /*break*/, 11];
49890
+ }
49891
+ return [3 /*break*/, 11];
49892
+ case 1:
49893
+ generator = new ClaudeCodeGenerator(cwd, config, verbose);
49894
+ return [4 /*yield*/, generator.generate(skipHooks)];
49895
+ case 2: return [2 /*return*/, _b.sent()];
49896
+ case 3:
49897
+ generator = new CursorGenerator(cwd, config, verbose);
49898
+ return [4 /*yield*/, generator.generate()];
49899
+ case 4: return [2 /*return*/, _b.sent()];
49900
+ case 5:
49901
+ generator = new WindsurfGenerator(cwd, config, verbose);
49902
+ return [4 /*yield*/, generator.generate()];
49903
+ case 6: return [2 /*return*/, _b.sent()];
49904
+ case 7:
49905
+ generator = new CoderGenerator(cwd, config, verbose);
49906
+ return [4 /*yield*/, generator.generate()];
49907
+ case 8: return [2 /*return*/, _b.sent()];
49908
+ case 9:
49909
+ generator = new AugmentGenerator(cwd, config, verbose);
49910
+ return [4 /*yield*/, generator.generate()];
49911
+ case 10: return [2 /*return*/, _b.sent()];
49912
+ case 11:
49913
+ {
49914
+ // 只生成基础配置,不生成工具特定文件
49915
+ if (verbose) {
49916
+ console.log('⏭️ 跳过工具特定配置');
49917
+ }
49918
+ return [2 /*return*/, {
49919
+ success: true,
49920
+ files: [],
49921
+ message: 'No tool-specific configuration generated',
49922
+ }];
49923
+ }
49924
+ case 12: return [2 /*return*/];
49925
+ }
49926
+ });
49927
+ });
49928
+ }
49929
+ /**
49930
+ * 获取工具的显示名称
49931
+ */
49932
+ function getToolName(tool) {
49933
+ var toolChoice = AI_TOOLS.find(function (t) { return t.value === tool; });
49934
+ return toolChoice ? toolChoice.name : tool;
49935
+ }
49936
+
48301
49937
  exports.ShadowSpace = ShadowSpace;
48302
49938
  exports.ShadowSpaceDebugger = ShadowSpaceDebugger;
48303
49939
  exports.TSXComplianceChecker = TSXComplianceChecker;
@@ -48316,6 +49952,7 @@ exports.generateFixSuggestions = generateFixSuggestions;
48316
49952
  exports.getPureValue = getPureValue;
48317
49953
  exports.initClaudeHooks = initClaudeHooks;
48318
49954
  exports.initSolution = initSolution;
49955
+ exports.initSpace = initSpace;
48319
49956
  exports.isFileCompliant = isFileCompliant;
48320
49957
  exports.releaseMaterial = releaseMaterial;
48321
49958
  exports.run = run;