@appthen/cli 1.2.6 → 1.2.7

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.
Files changed (2) hide show
  1. package/dist/index.js +300 -95
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -40834,7 +40834,31 @@ var ShadowSpace = /** @class */ (function () {
40834
40834
  case 4:
40835
40835
  writtenContent = _g.sent();
40836
40836
  localHash = this.calculateHash(writtenContent);
40837
+ console.log('localHash: ', localHash);
40837
40838
  remoteHash = file.hash || localHash;
40839
+ // 🔍 检测哈希差异,帮助诊断编码问题
40840
+ if (file.hash && file.hash !== localHash) {
40841
+ console.warn("[ShadowSpace] \u68C0\u6D4B\u5230\u54C8\u5E0C\u4E0D\u4E00\u81F4: ".concat(file.path), {
40842
+ editorHash: file.hash.substring(0, 16),
40843
+ localHash: localHash.substring(0, 16),
40844
+ editorHashFull: file.hash,
40845
+ localHashFull: localHash,
40846
+ contentLength: file.content.length,
40847
+ writtenLength: writtenContent.length,
40848
+ contentSame: file.content === writtenContent,
40849
+ filePath: file.path,
40850
+ });
40851
+ // 如果内容相同但哈希不同,可能是编码问题
40852
+ if (file.content === writtenContent) {
40853
+ console.error("[ShadowSpace] \u26A0\uFE0F \u5185\u5BB9\u76F8\u540C\u4F46\u54C8\u5E0C\u4E0D\u540C\uFF0C\u53EF\u80FD\u5B58\u5728\u7F16\u7801\u95EE\u9898: ".concat(file.path));
40854
+ }
40855
+ else {
40856
+ console.error("[ShadowSpace] \u26A0\uFE0F \u5185\u5BB9\u4E0D\u540C\uFF0C\u53EF\u80FD\u662F\u6587\u4EF6\u5199\u5165\u8FC7\u7A0B\u4E2D\u7684\u8F6C\u6362\u95EE\u9898: ".concat(file.path));
40857
+ // 显示前100个字符的差异
40858
+ console.log("\u7F16\u8F91\u5668\u5185\u5BB9\u524D100\u5B57\u7B26: ".concat(JSON.stringify(file.content.substring(0, 100))));
40859
+ console.log("\u5199\u5165\u5185\u5BB9\u524D100\u5B57\u7B26: ".concat(JSON.stringify(writtenContent.substring(0, 100))));
40860
+ }
40861
+ }
40838
40862
  newFiles[file.path] = {
40839
40863
  path: file.path,
40840
40864
  hash: localHash,
@@ -40997,31 +41021,32 @@ var ShadowSpace = /** @class */ (function () {
40997
41021
  };
40998
41022
  /**
40999
41023
  * 检测本地文件系统与影子空间的差异
41024
+ * 注意:跳过 remoteModified 标记的文件,避免与编辑器检测冲突
41000
41025
  */
41001
41026
  ShadowSpace.prototype.detectChanges = function () {
41002
41027
  var _a;
41003
41028
  return __awaiter(this, void 0, void 0, function () {
41004
- 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;
41005
- var e_3, _k, _l, _m, e_4, _o;
41006
- return __generator(this, function (_p) {
41007
- switch (_p.label) {
41029
+ var changes, _b, _c, _d, filePath, shadowEntry, localFilePath, localContent, localHash, fileStat, fileModifyTime, shadowContent, _e, _f, error_2, shadowContent, e_3_1, localFiles, localFiles_1, localFiles_1_1, localFile;
41030
+ var e_3, _g, _h, e_4, _j;
41031
+ return __generator(this, function (_k) {
41032
+ switch (_k.label) {
41008
41033
  case 0:
41009
41034
  changes = [];
41010
- _p.label = 1;
41035
+ _k.label = 1;
41011
41036
  case 1:
41012
- _p.trys.push([1, 16, 17, 18]);
41037
+ _k.trys.push([1, 16, 17, 18]);
41013
41038
  _b = __values(Object.entries(this.state.files)), _c = _b.next();
41014
- _p.label = 2;
41039
+ _k.label = 2;
41015
41040
  case 2:
41016
41041
  if (!!_c.done) return [3 /*break*/, 15];
41017
41042
  _d = __read(_c.value, 2), filePath = _d[0], shadowEntry = _d[1];
41018
41043
  localFilePath = path__default["default"].join(this.config.projectRoot, filePath);
41019
- _p.label = 3;
41044
+ _k.label = 3;
41020
41045
  case 3:
41021
- _p.trys.push([3, 11, , 14]);
41046
+ _k.trys.push([3, 11, , 14]);
41022
41047
  return [4 /*yield*/, fs__default$1["default"].readFile(localFilePath, 'utf8')];
41023
41048
  case 4:
41024
- localContent = _p.sent();
41049
+ localContent = _k.sent();
41025
41050
  localHash = this.calculateHash(localContent);
41026
41051
  if (!(localHash !== shadowEntry.hash)) return [3 /*break*/, 10];
41027
41052
  console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4: ".concat(filePath), {
@@ -41032,29 +41057,31 @@ var ShadowSpace = /** @class */ (function () {
41032
41057
  version: shadowEntry.version,
41033
41058
  });
41034
41059
  if (!shadowEntry.remoteModified) return [3 /*break*/, 7];
41035
- // 如果是远程修改,先更新影子空间记录并清除远程修改标记
41036
- console.log("\u68C0\u6D4B\u5230\u8FDC\u7A0B\u4FEE\u6539\u6587\u4EF6\u7684\u672C\u5730\u53D8\u5316: ".concat(filePath));
41037
- // 更新影子空间记录
41038
- _e = this.state.files;
41039
- _f = filePath;
41040
- _g = [__assign({}, shadowEntry)];
41041
- _l = { hash: localHash };
41060
+ console.log("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u4FEE\u6539\u6587\u4EF6\u7684\u672C\u5730\u68C0\u6D4B: ".concat(filePath, "\uFF0C\u5C06\u7531\u65F6\u95F4\u6233\u6BD4\u5BF9\u51B3\u5B9A\u65B9\u5411"));
41042
41061
  return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
41043
41062
  case 5:
41044
- _l.size = (_p.sent()).size, _l.lastSyncTime = Date.now(), _l.version = shadowEntry.version + 1;
41045
- return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
41063
+ fileStat = _k.sent();
41064
+ fileModifyTime = fileStat.mtimeMs;
41065
+ console.log("[ShadowSpace] \uD83D\uDD0D \u66F4\u65B0\u6587\u4EF6\u65F6\u95F4\u6233: ".concat(filePath), {
41066
+ 旧lastModified: new Date(shadowEntry.lastModified || 0).toISOString(),
41067
+ 旧mtime: new Date(shadowEntry.mtime || 0).toISOString(),
41068
+ 新fileModifyTime: new Date(fileModifyTime).toISOString(),
41069
+ 时间戳是否变化: fileModifyTime !== shadowEntry.lastModified,
41070
+ });
41071
+ // 更新影子空间记录,清除远程修改标记
41072
+ this.state.files[filePath] = __assign(__assign({}, shadowEntry), { hash: localHash, size: fileStat.size, lastSyncTime: Date.now(), version: shadowEntry.version + 1, mtime: fileModifyTime, lastModified: fileModifyTime, remoteModified: false });
41073
+ // 保存状态
41074
+ return [4 /*yield*/, this.saveState()];
41046
41075
  case 6:
41047
- // 更新影子空间记录
41048
- _e[_f] = __assign.apply(void 0, _g.concat([(_l.mtime = (_p.sent()).mtimeMs, _l.remoteModified = false, _l)]));
41049
- // 如果本地内容与最初的远程内容不同,则认为是本地修改
41050
- // 这里我们简化处理:任何在远程修改基础上的本地变化都视为本地修改
41051
- 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"));
41052
- _p.label = 7;
41076
+ // 保存状态
41077
+ _k.sent();
41078
+ // 🔥 跳过,不添加到 changes
41079
+ return [3 /*break*/, 14];
41053
41080
  case 7: return [4 /*yield*/, this.getShadowContent(filePath)];
41054
41081
  case 8:
41055
- shadowContent = _p.sent();
41056
- _j = (_h = changes).push;
41057
- _m = {
41082
+ shadowContent = _k.sent();
41083
+ _f = (_e = changes).push;
41084
+ _h = {
41058
41085
  id: this.generateId(),
41059
41086
  action: 'modify',
41060
41087
  path: filePath,
@@ -41062,21 +41089,21 @@ var ShadowSpace = /** @class */ (function () {
41062
41089
  };
41063
41090
  return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
41064
41091
  case 9:
41065
- _j.apply(_h, [(_m.timestamp = (_p.sent()).mtime.getTime(),
41066
- _m.diff = {
41092
+ _f.apply(_e, [(_h.timestamp = (_k.sent()).mtime.getTime(),
41093
+ _h.diff = {
41067
41094
  before: shadowContent,
41068
41095
  after: localContent,
41069
41096
  },
41070
- _m.projectId = this.state.projectId,
41071
- _m)]);
41072
- _p.label = 10;
41097
+ _h.projectId = this.state.projectId,
41098
+ _h)]);
41099
+ _k.label = 10;
41073
41100
  case 10: return [3 /*break*/, 14];
41074
41101
  case 11:
41075
- error_2 = _p.sent();
41102
+ error_2 = _k.sent();
41076
41103
  if (!(error_2.code === 'ENOENT')) return [3 /*break*/, 13];
41077
41104
  return [4 /*yield*/, this.getShadowContent(filePath)];
41078
41105
  case 12:
41079
- shadowContent = _p.sent();
41106
+ shadowContent = _k.sent();
41080
41107
  changes.push({
41081
41108
  id: this.generateId(),
41082
41109
  action: 'delete',
@@ -41089,25 +41116,25 @@ var ShadowSpace = /** @class */ (function () {
41089
41116
  },
41090
41117
  projectId: this.state.projectId,
41091
41118
  });
41092
- _p.label = 13;
41119
+ _k.label = 13;
41093
41120
  case 13: return [3 /*break*/, 14];
41094
41121
  case 14:
41095
41122
  _c = _b.next();
41096
41123
  return [3 /*break*/, 2];
41097
41124
  case 15: return [3 /*break*/, 18];
41098
41125
  case 16:
41099
- e_3_1 = _p.sent();
41126
+ e_3_1 = _k.sent();
41100
41127
  e_3 = { error: e_3_1 };
41101
41128
  return [3 /*break*/, 18];
41102
41129
  case 17:
41103
41130
  try {
41104
- if (_c && !_c.done && (_k = _b.return)) _k.call(_b);
41131
+ if (_c && !_c.done && (_g = _b.return)) _g.call(_b);
41105
41132
  }
41106
41133
  finally { if (e_3) throw e_3.error; }
41107
41134
  return [7 /*endfinally*/];
41108
41135
  case 18: return [4 /*yield*/, this.scanLocalFiles()];
41109
41136
  case 19:
41110
- localFiles = _p.sent();
41137
+ localFiles = _k.sent();
41111
41138
  try {
41112
41139
  for (localFiles_1 = __values(localFiles), localFiles_1_1 = localFiles_1.next(); !localFiles_1_1.done; localFiles_1_1 = localFiles_1.next()) {
41113
41140
  localFile = localFiles_1_1.value;
@@ -41130,7 +41157,7 @@ var ShadowSpace = /** @class */ (function () {
41130
41157
  catch (e_4_1) { e_4 = { error: e_4_1 }; }
41131
41158
  finally {
41132
41159
  try {
41133
- if (localFiles_1_1 && !localFiles_1_1.done && (_o = localFiles_1.return)) _o.call(localFiles_1);
41160
+ if (localFiles_1_1 && !localFiles_1_1.done && (_j = localFiles_1.return)) _j.call(localFiles_1);
41134
41161
  }
41135
41162
  finally { if (e_4) throw e_4.error; }
41136
41163
  }
@@ -41421,29 +41448,41 @@ var ShadowSpace = /** @class */ (function () {
41421
41448
  * 用于与编辑器快照进行比对
41422
41449
  */
41423
41450
  ShadowSpace.prototype.getSpaceSnapshots = function (_spaceId) {
41451
+ var _a, _b;
41424
41452
  return __awaiter(this, void 0, void 0, function () {
41425
- var snapshots, _a, _b, _c, filePath, shadowEntry, error_6;
41426
- var e_8, _d;
41427
- return __generator(this, function (_e) {
41428
- switch (_e.label) {
41453
+ var snapshots, _c, _d, _e, filePath, shadowEntry, modifyTime, error_6;
41454
+ var e_8, _f;
41455
+ return __generator(this, function (_g) {
41456
+ switch (_g.label) {
41429
41457
  case 0:
41430
- _e.trys.push([0, 2, , 3]);
41458
+ _g.trys.push([0, 2, , 3]);
41431
41459
  // 确保状态已加载
41432
41460
  return [4 /*yield*/, this.loadState()];
41433
41461
  case 1:
41434
41462
  // 确保状态已加载
41435
- _e.sent();
41463
+ _g.sent();
41436
41464
  snapshots = [];
41437
41465
  try {
41438
41466
  // 遍历影子空间中的所有文件
41439
- for (_a = __values(Object.entries(this.state.files)), _b = _a.next(); !_b.done; _b = _a.next()) {
41440
- _c = __read(_b.value, 2), filePath = _c[0], shadowEntry = _c[1];
41467
+ for (_c = __values(Object.entries(this.state.files)), _d = _c.next(); !_d.done; _d = _c.next()) {
41468
+ _e = __read(_d.value, 2), filePath = _e[0], shadowEntry = _e[1];
41469
+ // 🔍 调试哈希差异
41470
+ if (shadowEntry.hash !== shadowEntry.remoteHash) {
41471
+ console.log("[ShadowSpace] \u5FEB\u7167\u4E2D\u7684\u54C8\u5E0C\u5DEE\u5F02: ".concat(filePath), {
41472
+ localHash: (_a = shadowEntry.hash) === null || _a === void 0 ? void 0 : _a.substring(0, 16),
41473
+ remoteHash: (_b = shadowEntry.remoteHash) === null || _b === void 0 ? void 0 : _b.substring(0, 16),
41474
+ localHashFull: shadowEntry.hash,
41475
+ remoteHashFull: shadowEntry.remoteHash,
41476
+ remoteModified: shadowEntry.remoteModified,
41477
+ });
41478
+ }
41479
+ modifyTime = shadowEntry.mtime ||
41480
+ shadowEntry.lastModified ||
41481
+ shadowEntry.lastSyncTime ||
41482
+ Date.now();
41441
41483
  snapshots.push({
41442
41484
  path: filePath,
41443
- modify: shadowEntry.lastModified ||
41444
- shadowEntry.mtime ||
41445
- shadowEntry.lastSyncTime ||
41446
- Date.now(),
41485
+ modify: modifyTime,
41447
41486
  hash: shadowEntry.hash,
41448
41487
  remoteHash: shadowEntry.remoteHash || shadowEntry.hash,
41449
41488
  updateBy: shadowEntry.remoteModified ? 'shadow-space' : 'local',
@@ -41455,14 +41494,14 @@ var ShadowSpace = /** @class */ (function () {
41455
41494
  catch (e_8_1) { e_8 = { error: e_8_1 }; }
41456
41495
  finally {
41457
41496
  try {
41458
- if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
41497
+ if (_d && !_d.done && (_f = _c.return)) _f.call(_c);
41459
41498
  }
41460
41499
  finally { if (e_8) throw e_8.error; }
41461
41500
  }
41462
41501
  console.log("[ShadowSpace] \u83B7\u53D6\u7A7A\u95F4\u5FEB\u7167: ".concat(snapshots.length, " \u4E2A\u6587\u4EF6"));
41463
41502
  return [2 /*return*/, snapshots];
41464
41503
  case 2:
41465
- error_6 = _e.sent();
41504
+ error_6 = _g.sent();
41466
41505
  console.error("[ShadowSpace] \u83B7\u53D6\u7A7A\u95F4\u5FEB\u7167\u5931\u8D25:", error_6);
41467
41506
  return [2 /*return*/, []]; // 返回空数组而不是 undefined
41468
41507
  case 3: return [2 /*return*/];
@@ -41665,7 +41704,11 @@ var ShadowSpace = /** @class */ (function () {
41665
41704
  });
41666
41705
  };
41667
41706
  ShadowSpace.prototype.calculateHash = function (content) {
41668
- return crypto__default["default"].createHash('sha256').update(content, 'utf8').digest('hex');
41707
+ var normalizedContent = content.replace(/\r\n/g, '\n');
41708
+ return crypto__default["default"]
41709
+ .createHash('sha256')
41710
+ .update(normalizedContent, 'utf8')
41711
+ .digest('hex');
41669
41712
  };
41670
41713
  ShadowSpace.prototype.generateId = function () {
41671
41714
  return "change_".concat(Date.now(), "_").concat(Math.random().toString(36).substr(2, 9));
@@ -42809,7 +42852,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42809
42852
  filePaths: filePaths || null,
42810
42853
  timestamp: Date.now(),
42811
42854
  };
42812
- console.log("[ShadowSpace] \u8FDC\u7A0B\u4FEE\u6539\u6807\u8BB0\u6E05\u9664\u5B8C\u6210");
42855
+ console.log('[ShadowSpace] 远程修改标记清除完成');
42813
42856
  return [2 /*return*/, result];
42814
42857
  }
42815
42858
  });
@@ -42900,28 +42943,155 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42900
42943
  */
42901
42944
  ShadowSpaceCommandHandler.prototype.detectEditorChanges = function (spaceId, editorSnapshots) {
42902
42945
  return __awaiter(this, void 0, void 0, function () {
42903
- var safeEditorSnapshots, spaceSnapshots, changes, summary, error_3;
42946
+ var safeEditorSnapshots, localChanges, spaceSnapshots, spaceInfo, fs, spaceDir, spaceExists, files, error_3, snapshotChanges, localAddChanges, changes, summary, error_4;
42904
42947
  return __generator(this, function (_a) {
42905
42948
  switch (_a.label) {
42906
42949
  case 0:
42907
- _a.trys.push([0, 3, , 4]);
42950
+ _a.trys.push([0, 9, , 10]);
42908
42951
  safeEditorSnapshots = Array.isArray(editorSnapshots)
42909
42952
  ? editorSnapshots
42910
42953
  : [];
42911
- return [4 /*yield*/, this.shadowSpace.getSpaceSnapshots(spaceId)];
42954
+ // console.log(
42955
+ // `[ShadowSpace] 开始检测变更: 空间=${spaceId}, 编辑器文件=${safeEditorSnapshots.length}个`
42956
+ // );
42957
+ // 1. 🔥 先检测本地文件变更,更新影子空间状态,并获取本地变更列表(包括新增文件)
42958
+ console.log("\n\uD83D\uDD0D [DEBUG] \u6B63\u5728\u68C0\u6D4B\u672C\u5730\u6587\u4EF6\u53D8\u66F4...");
42959
+ return [4 /*yield*/, this.shadowSpace.detectChanges()];
42912
42960
  case 1:
42961
+ localChanges = _a.sent();
42962
+ console.log("\uD83D\uDD0D [DEBUG] \u672C\u5730\u6587\u4EF6\u53D8\u66F4\u68C0\u6D4B\u5B8C\u6210\uFF0C\u68C0\u6D4B\u5230 ".concat(localChanges.length, " \u4E2A\u672C\u5730\u53D8\u66F4"));
42963
+ // 2. 读取空间快照
42964
+ console.log("\n\uD83D\uDD0D [DEBUG] \u6B63\u5728\u83B7\u53D6\u7A7A\u95F4\u5FEB\u7167\uFF0C\u7A7A\u95F4ID: ".concat(spaceId));
42965
+ return [4 /*yield*/, this.shadowSpace.getSpaceSnapshots(spaceId)];
42966
+ case 2:
42913
42967
  spaceSnapshots = _a.sent();
42968
+ console.log("\uD83D\uDD0D [DEBUG] getSpaceSnapshots \u8FD4\u56DE\u7ED3\u679C\u7C7B\u578B: ".concat(typeof spaceSnapshots));
42969
+ console.log("\uD83D\uDD0D [DEBUG] getSpaceSnapshots \u662F\u5426\u4E3A\u6570\u7EC4: ".concat(Array.isArray(spaceSnapshots)));
42970
+ console.log("\uD83D\uDD0D [DEBUG] getSpaceSnapshots \u539F\u59CB\u7ED3\u679C:", spaceSnapshots);
42971
+ // 🔍 友好的调试输出
42972
+ console.log('\n=== 影子空间变更检测调试 ===');
42973
+ console.log('📁 空间ID:', spaceId);
42974
+ console.log('📊 编辑器快照数量:', safeEditorSnapshots.length);
42975
+ console.log('📁 空间快照数量:', Array.isArray(spaceSnapshots) ? spaceSnapshots.length : 0);
42976
+ spaceInfo = this.shadowSpace.getSpaceInfo();
42977
+ console.log('\n🏠 影子空间信息:');
42978
+ console.log(" \uD83D\uDCC2 \u9879\u76EE\u6839\u76EE\u5F55: ".concat(spaceInfo.projectRoot));
42979
+ console.log(" \uD83D\uDCC1 \u7A7A\u95F4\u76EE\u5F55: ".concat(spaceInfo.spaceRoot));
42980
+ console.log(" \uD83D\uDCCA \u6587\u4EF6\u6570\u91CF: ".concat(spaceInfo.fileCount));
42981
+ console.log(" \uD83D\uDCE6 \u603B\u5927\u5C0F: ".concat(spaceInfo.totalSize));
42982
+ console.log(" \uD83C\uDD94 \u7528\u6237ID: ".concat(spaceInfo.userId));
42983
+ console.log(" \u23F0 \u521B\u5EFA\u65F6\u95F4: ".concat(spaceInfo.createdAt));
42984
+ console.log(" \u23F0 \u66F4\u65B0\u65F6\u95F4: ".concat(spaceInfo.updatedAt));
42985
+ require('path');
42986
+ fs = require('fs-extra');
42987
+ spaceDir = spaceInfo.spaceRoot;
42988
+ return [4 /*yield*/, fs.pathExists(spaceDir)];
42989
+ case 3:
42990
+ spaceExists = _a.sent();
42991
+ console.log("\n\uD83D\uDCC1 \u7A7A\u95F4\u76EE\u5F55\u68C0\u67E5:");
42992
+ console.log(" \uD83D\uDCC2 \u8DEF\u5F84: ".concat(spaceDir));
42993
+ console.log(" \u2705 \u662F\u5426\u5B58\u5728: ".concat(spaceExists));
42994
+ if (!spaceExists) return [3 /*break*/, 7];
42995
+ _a.label = 4;
42996
+ case 4:
42997
+ _a.trys.push([4, 6, , 7]);
42998
+ return [4 /*yield*/, fs.readdir(spaceDir)];
42999
+ case 5:
43000
+ files = _a.sent();
43001
+ console.log(" \uD83D\uDCC4 \u76EE\u5F55\u5185\u5BB9: ".concat(files.slice(0, 10).join(', ')).concat(files.length > 10 ? '...' : ''));
43002
+ return [3 /*break*/, 7];
43003
+ case 6:
43004
+ error_3 = _a.sent();
43005
+ console.log(" \u274C \u8BFB\u53D6\u76EE\u5F55\u5931\u8D25: ".concat(error_3.message));
43006
+ return [3 /*break*/, 7];
43007
+ case 7:
43008
+ // 编辑器快照详情(显示前5个)
43009
+ if (safeEditorSnapshots.length > 0) {
43010
+ console.log('\n📝 编辑器快照详情 (前5个):');
43011
+ safeEditorSnapshots.slice(0, 5).forEach(function (file, index) {
43012
+ var _a;
43013
+ console.log(" [".concat(index + 1, "] ").concat(file.path));
43014
+ console.log(" \uD83D\uDD11 hash: ".concat((_a = file.hash) === null || _a === void 0 ? void 0 : _a.substring(0, 16), "..."));
43015
+ console.log(" \u23F0 modified: ".concat(file.lastModified));
43016
+ });
43017
+ if (safeEditorSnapshots.length > 5) {
43018
+ console.log(" ... \u8FD8\u6709 ".concat(safeEditorSnapshots.length - 5, " \u4E2A\u6587\u4EF6"));
43019
+ }
43020
+ }
43021
+ // 空间快照详情(显示前5个)
43022
+ if (Array.isArray(spaceSnapshots) && spaceSnapshots.length > 0) {
43023
+ console.log('\n💾 空间快照详情 (前5个):');
43024
+ spaceSnapshots.slice(0, 5).forEach(function (file, index) {
43025
+ var _a, _b;
43026
+ console.log(" [".concat(index + 1, "] ").concat(file.path));
43027
+ console.log(" \uD83D\uDD11 \u672C\u5730hash: ".concat((_a = file.hash) === null || _a === void 0 ? void 0 : _a.substring(0, 16), "..."));
43028
+ console.log(" \u2601\uFE0F \u4E91\u7AEFhash: ".concat((_b = file.remoteHash) === null || _b === void 0 ? void 0 : _b.substring(0, 16), "..."));
43029
+ console.log(" \u23F0 modified: ".concat(file.lastModified));
43030
+ });
43031
+ if (spaceSnapshots.length > 5) {
43032
+ console.log(" ... \u8FD8\u6709 ".concat(spaceSnapshots.length - 5, " \u4E2A\u6587\u4EF6"));
43033
+ }
43034
+ }
42914
43035
  Array.isArray(spaceSnapshots)
42915
43036
  ? spaceSnapshots.length
42916
43037
  : 0;
42917
43038
  return [4 /*yield*/, this.compareSnapshots(safeEditorSnapshots, spaceSnapshots)];
42918
- case 2:
42919
- changes = _a.sent();
43039
+ case 8:
43040
+ snapshotChanges = _a.sent();
43041
+ localAddChanges = localChanges
43042
+ .filter(function (change) { return change.action === 'add'; })
43043
+ .map(function (change) { return ({
43044
+ action: 'add',
43045
+ path: change.path,
43046
+ side: 'space',
43047
+ sourceLabel: 'shadow-space',
43048
+ targetLabel: 'editor',
43049
+ // 本地新增文件,编辑器中不存在,所以 editorHash 为空
43050
+ editorHash: undefined,
43051
+ // spaceHash 可以从文件内容计算,但这里我们不需要,因为前端只需要知道是新增文件
43052
+ spaceHash: undefined,
43053
+ }); });
43054
+ console.log("\uD83D\uDD0D [DEBUG] \u672C\u5730\u65B0\u589E\u6587\u4EF6\u6570\u91CF: ".concat(localAddChanges.length));
43055
+ if (localAddChanges.length > 0) {
43056
+ console.log("\uD83D\uDD0D [DEBUG] \u672C\u5730\u65B0\u589E\u6587\u4EF6\u5217\u8868:", localAddChanges.map(function (c) { return c.path; }));
43057
+ }
43058
+ changes = __spreadArray(__spreadArray([], __read(snapshotChanges), false), __read(localAddChanges), false);
42920
43059
  summary = {
42921
43060
  total: changes.length,
42922
43061
  needPush: changes.filter(function (c) { return c.side === 'editor'; }).length,
42923
43062
  needPull: changes.filter(function (c) { return c.side === 'space'; }).length,
42924
43063
  };
43064
+ // 🔍 变更结果详细分析
43065
+ console.log('\n📋 变更检测结果:');
43066
+ console.log(" \uD83D\uDCCA \u603B\u53D8\u66F4\u6570: ".concat(summary.total));
43067
+ console.log(" \u2B06\uFE0F \u9700\u8981\u63A8\u9001: ".concat(summary.needPush, " \u4E2A\u6587\u4EF6"));
43068
+ console.log(" \u2B07\uFE0F \u9700\u8981\u62C9\u53D6: ".concat(summary.needPull, " \u4E2A\u6587\u4EF6"));
43069
+ if (changes.length > 0) {
43070
+ console.log('\n📝 变更详情:');
43071
+ changes.forEach(function (change, index) {
43072
+ var _a, _b, _c, _d;
43073
+ var actionIcon = change.action === 'add'
43074
+ ? '➕'
43075
+ : change.action === 'modify'
43076
+ ? '🔄'
43077
+ : change.action === 'delete'
43078
+ ? '🗑️'
43079
+ : '❓';
43080
+ var directionIcon = change.side === 'editor' ? '⬆️' : '⬇️';
43081
+ console.log(" [".concat(index + 1, "] ").concat(actionIcon, " ").concat(change.action.toUpperCase(), ": ").concat(change.path));
43082
+ console.log(" ".concat(directionIcon, " \u65B9\u5411: ").concat(change.side === 'editor' ? '编辑器→空间' : '空间→编辑器'));
43083
+ if (change.action === 'modify') {
43084
+ console.log(" \uD83D\uDD11 \u6BD4\u5BF9: ".concat((_a = change.editorHash) === null || _a === void 0 ? void 0 : _a.substring(0, 16), "... vs ").concat((_b = change.spaceHash) === null || _b === void 0 ? void 0 : _b.substring(0, 16), "..."));
43085
+ }
43086
+ else if (change.action === 'add') {
43087
+ console.log(" \uD83D\uDD11 hash: ".concat((_c = change.editorHash) === null || _c === void 0 ? void 0 : _c.substring(0, 16), "..."));
43088
+ }
43089
+ else if (change.action === 'delete') {
43090
+ console.log(" \uD83D\uDD11 hash: ".concat((_d = change.spaceHash) === null || _d === void 0 ? void 0 : _d.substring(0, 16), "..."));
43091
+ }
43092
+ });
43093
+ }
43094
+ console.log('=== 调试信息结束 ===\n');
42925
43095
  // console.log(
42926
43096
  // `[ShadowSpace] 变更检测完成: 总计${summary.total}个变更, 需推送${summary.needPush}个, 需拉取${summary.needPull}个`
42927
43097
  // );
@@ -42935,27 +43105,29 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42935
43105
  summary: summary,
42936
43106
  },
42937
43107
  }];
42938
- case 3:
42939
- error_3 = _a.sent();
42940
- console.error("[ShadowSpace] \u68C0\u6D4B\u53D8\u66F4\u5931\u8D25:", error_3);
43108
+ case 9:
43109
+ error_4 = _a.sent();
43110
+ console.error('[ShadowSpace] 检测变更失败:', error_4);
42941
43111
  return [2 /*return*/, {
42942
43112
  success: false,
42943
- error: error_3 instanceof Error ? error_3.message : '检测变更失败',
43113
+ error: error_4 instanceof Error ? error_4.message : '检测变更失败',
42944
43114
  }];
42945
- case 4: return [2 /*return*/];
43115
+ case 10: return [2 /*return*/];
42946
43116
  }
42947
43117
  });
42948
43118
  });
42949
43119
  };
42950
43120
  /**
42951
43121
  * 比对编辑器和空间快照
43122
+ * 现在 hash 算法已统一,可以直接比对 hash
43123
+ * 当 hash 不同时,通过时间戳判断谁是最新版本
42952
43124
  */
42953
43125
  ShadowSpaceCommandHandler.prototype.compareSnapshots = function (editorSnapshots, spaceSnapshots) {
42954
- var _a, _b, _c;
43126
+ var _a, _b;
42955
43127
  return __awaiter(this, void 0, void 0, function () {
42956
- var changes, safeEditorSnapshots, safeSpaceSnapshots, editorMap, spaceMap, editorMap_1, editorMap_1_1, _d, path, editorFile, spaceFile, spaceMap_1, spaceMap_1_1, _e, path, spaceFile, editorFile;
42957
- var e_2, _f, e_3, _g;
42958
- return __generator(this, function (_h) {
43128
+ var changes, safeEditorSnapshots, safeSpaceSnapshots, editorMap, spaceMap, editorMap_1, editorMap_1_1, _c, path, editorFile, spaceFile, editorModify, spaceModify, spaceMap_1, spaceMap_1_1, _d, path, spaceFile, editorFile;
43129
+ var e_2, _e, e_3, _f;
43130
+ return __generator(this, function (_g) {
42959
43131
  changes = [];
42960
43132
  safeEditorSnapshots = Array.isArray(editorSnapshots)
42961
43133
  ? editorSnapshots
@@ -42968,10 +43140,10 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42968
43140
  try {
42969
43141
  // 检测编辑器的变更(新增、修改)
42970
43142
  for (editorMap_1 = __values(editorMap), editorMap_1_1 = editorMap_1.next(); !editorMap_1_1.done; editorMap_1_1 = editorMap_1.next()) {
42971
- _d = __read(editorMap_1_1.value, 2), path = _d[0], editorFile = _d[1];
43143
+ _c = __read(editorMap_1_1.value, 2), path = _c[0], editorFile = _c[1];
42972
43144
  spaceFile = spaceMap.get(path);
42973
43145
  if (!spaceFile) {
42974
- // 编辑器新增的文件
43146
+ // 编辑器新增的文件 → 推送到空间
42975
43147
  changes.push({
42976
43148
  action: 'add',
42977
43149
  path: path,
@@ -42982,41 +43154,75 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
42982
43154
  spaceHash: null,
42983
43155
  });
42984
43156
  }
42985
- else if (editorFile.hash !== spaceFile.remoteHash) {
42986
- // 编辑器修改的文件(基于云端哈希比对)
42987
- console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u7F16\u8F91\u5668\u4FEE\u6539: ".concat(path), {
43157
+ else if (editorFile.hash !== spaceFile.hash) {
43158
+ editorModify = editorFile.modify || 0;
43159
+ spaceModify = spaceFile.modify || 0;
43160
+ console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u5DEE\u5F02: ".concat(path), {
42988
43161
  editorHash: (_a = editorFile.hash) === null || _a === void 0 ? void 0 : _a.substring(0, 16),
42989
- spaceRemoteHash: (_b = spaceFile.remoteHash) === null || _b === void 0 ? void 0 : _b.substring(0, 16),
42990
- spaceLocalHash: (_c = spaceFile.hash) === null || _c === void 0 ? void 0 : _c.substring(0, 16),
42991
- editorHashFull: editorFile.hash,
42992
- spaceRemoteHashFull: spaceFile.remoteHash,
42993
- });
42994
- changes.push({
42995
- action: 'modify',
42996
- path: path,
42997
- side: 'editor',
42998
- sourceLabel: 'editor',
42999
- targetLabel: 'shadow-space',
43000
- editorHash: editorFile.hash,
43001
- spaceHash: spaceFile.remoteHash,
43162
+ spaceHash: (_b = spaceFile.hash) === null || _b === void 0 ? void 0 : _b.substring(0, 16),
43163
+ editorModify: new Date(editorModify).toISOString(),
43164
+ spaceModify: new Date(spaceModify).toISOString(),
43165
+ editorUpdateBy: editorFile.updateBy,
43166
+ spaceUpdateBy: spaceFile.updateBy,
43002
43167
  });
43168
+ // 🔥 关键逻辑:根据时间戳判断方向
43169
+ if (editorModify > spaceModify) {
43170
+ // 编辑器更新 → 推送到空间
43171
+ console.log("[ShadowSpace] \u2192 \u7F16\u8F91\u5668\u66F4\u65B0\uFF0C\u9700\u8981\u63A8\u9001: ".concat(path));
43172
+ changes.push({
43173
+ action: 'modify',
43174
+ path: path,
43175
+ side: 'editor',
43176
+ sourceLabel: 'editor',
43177
+ targetLabel: 'shadow-space',
43178
+ editorHash: editorFile.hash,
43179
+ spaceHash: spaceFile.hash,
43180
+ });
43181
+ }
43182
+ else if (spaceModify > editorModify) {
43183
+ // 空间更新 → 拉取到编辑器
43184
+ console.log("[ShadowSpace] \u2190 \u7A7A\u95F4\u66F4\u65B0\uFF0C\u9700\u8981\u62C9\u53D6: ".concat(path));
43185
+ changes.push({
43186
+ action: 'modify',
43187
+ path: path,
43188
+ side: 'space',
43189
+ sourceLabel: 'shadow-space',
43190
+ targetLabel: 'editor',
43191
+ editorHash: editorFile.hash,
43192
+ spaceHash: spaceFile.hash,
43193
+ });
43194
+ }
43195
+ else {
43196
+ // 时间戳相同但 hash 不同 → 可能是冲突,默认以编辑器为准
43197
+ console.warn("[ShadowSpace] \u26A0\uFE0F \u65F6\u95F4\u6233\u76F8\u540C\u4F46\u5185\u5BB9\u4E0D\u540C\uFF0C\u9ED8\u8BA4\u4EE5\u7F16\u8F91\u5668\u4E3A\u51C6: ".concat(path));
43198
+ changes.push({
43199
+ action: 'modify',
43200
+ path: path,
43201
+ side: 'editor',
43202
+ sourceLabel: 'editor',
43203
+ targetLabel: 'shadow-space',
43204
+ editorHash: editorFile.hash,
43205
+ spaceHash: spaceFile.hash,
43206
+ conflict: true, // 标记为潜在冲突
43207
+ });
43208
+ }
43003
43209
  }
43004
43210
  }
43005
43211
  }
43006
43212
  catch (e_2_1) { e_2 = { error: e_2_1 }; }
43007
43213
  finally {
43008
43214
  try {
43009
- if (editorMap_1_1 && !editorMap_1_1.done && (_f = editorMap_1.return)) _f.call(editorMap_1);
43215
+ if (editorMap_1_1 && !editorMap_1_1.done && (_e = editorMap_1.return)) _e.call(editorMap_1);
43010
43216
  }
43011
43217
  finally { if (e_2) throw e_2.error; }
43012
43218
  }
43013
43219
  try {
43014
- // 检测空间的变更(删除、空间独有的修改)
43220
+ // 检测空间独有的文件(编辑器已删除或空间新增)
43015
43221
  for (spaceMap_1 = __values(spaceMap), spaceMap_1_1 = spaceMap_1.next(); !spaceMap_1_1.done; spaceMap_1_1 = spaceMap_1.next()) {
43016
- _e = __read(spaceMap_1_1.value, 2), path = _e[0], spaceFile = _e[1];
43222
+ _d = __read(spaceMap_1_1.value, 2), path = _d[0], spaceFile = _d[1];
43017
43223
  editorFile = editorMap.get(path);
43018
43224
  if (!editorFile) {
43019
- // 空间独有的文件(编辑器已删除)
43225
+ // 空间独有的文件 → 拉取到编辑器(或编辑器已删除)
43020
43226
  changes.push({
43021
43227
  action: 'delete',
43022
43228
  path: path,
@@ -43024,16 +43230,15 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
43024
43230
  sourceLabel: 'shadow-space',
43025
43231
  targetLabel: 'editor',
43026
43232
  editorHash: null,
43027
- spaceHash: spaceFile.remoteHash,
43233
+ spaceHash: spaceFile.hash,
43028
43234
  });
43029
43235
  }
43030
- // 注意:空间的本地修改不在这里处理,因为我们主要关注编辑器 vs 云端哈希的比对
43031
43236
  }
43032
43237
  }
43033
43238
  catch (e_3_1) { e_3 = { error: e_3_1 }; }
43034
43239
  finally {
43035
43240
  try {
43036
- if (spaceMap_1_1 && !spaceMap_1_1.done && (_g = spaceMap_1.return)) _g.call(spaceMap_1);
43241
+ if (spaceMap_1_1 && !spaceMap_1_1.done && (_f = spaceMap_1.return)) _f.call(spaceMap_1);
43037
43242
  }
43038
43243
  finally { if (e_3) throw e_3.error; }
43039
43244
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appthen/cli",
3
- "version": "1.2.6",
3
+ "version": "1.2.7",
4
4
  "description": "Appthen Cli Tool",
5
5
  "files": [
6
6
  "dist",