dsh-vscode-mode 0.4.2 → 0.4.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/README.md CHANGED
@@ -91,6 +91,10 @@
91
91
  编辑器未打开时显示紧凑「差异 N 个文件 · 查看下一个」按钮(点击自动打开侧栏编辑器并聚焦差异);编辑器打开后 dock 切换为
92
92
  完整操作条(Keep / Undo / 跳转 / 回滚 / 归档对比),不会再出现第二个差异栏。header 差异角标 +
93
93
  DiffLauncher 全局总览 + 归档/批次回滚;状态持久化到工作区旁车(`.dsh-edit-review.json`,重启不丢)。
94
+ ⚠️ v0.4.3 修复「冲突差异可看不可点」:pending hunk 的 `newText` 已被后续修改覆盖(定位失败)时,host 会标记
95
+ `conflict` 并保留在待处理列表供复核,但单文件 Keep/Undo 原先只认「可定位」差异 → 这类文件恒留在差异栏且按钮置灰,
96
+ 而全局 Keep All / Undo All 却是亮的。现在单文件 Keep/Undo 覆盖冲突差异:Keep 记账后归档;Undo 对已不在文件中的
97
+ 差异不改动文件、直接按不采纳归档(状态栏提示「其中 N 处已不存在于文件,未改动」)。
94
98
  - **Monaco 离线分发**:`assets/vendor/monaco` AMD 构建随包发布,经 `/edrv/vendor/*` 前缀路由提供,全离线可用。
95
99
  版本锁定 `monaco-editor@0.42.0-dev-20230906`(commit `e7d7a5b0`),由 `node scripts/vendor-monaco.mjs [--force]`
96
100
  从 npm registry 复现铺入(内含版本+commit 双重断言,防静默换错构建)。
package/lib/client.js CHANGED
@@ -4278,6 +4278,17 @@ window.__ModuleLoader__.load({
4278
4278
  return activePath ? "editor" : "editor-empty";
4279
4279
  }
4280
4280
  /**
4281
+ * 文件是否仍可执行 Keep/Undo:可定位差异与无法定位的冲突差异都算待处理。
4282
+ * 冲突差异的 newText 已不在文件中(被后续修改覆盖),由 host 按"已不存在"记录决策。
4283
+ * @author ddj 2026年09月15号
4284
+ * @param pendingCount 可定位的待处理差异数
4285
+ * @param staleCount 无法定位(冲突)的待处理差异数
4286
+ * @returns 两者任一大于 0 时为 true
4287
+ */
4288
+ function canDecideFile(pendingCount, staleCount) {
4289
+ return Math.max(0, pendingCount) + Math.max(0, staleCount) > 0;
4290
+ }
4291
+ /**
4281
4292
  * 获取切换文件期间稳定展示的文件内差异数量。
4282
4293
  * @author ddj 2026年08月26号
4283
4294
  * @param ready 当前文件内容是否已加载完成
@@ -7222,6 +7233,7 @@ window.__ModuleLoader__.load({
7222
7233
  ]);
7223
7234
  const pendingRegions = react.default.useMemo(() => regions.filter((r) => r.status === ST.PENDING && !r.stale), [regions]);
7224
7235
  const staleRegions = react.default.useMemo(() => regions.filter((r) => r.status === ST.PENDING && r.stale), [regions]);
7236
+ const decideRegions = react.default.useMemo(() => [...pendingRegions, ...staleRegions], [pendingRegions, staleRegions]);
7225
7237
  hoverRegionsRef.current = pendingRegions;
7226
7238
  lineRegionMapRef.current = react.default.useMemo(() => {
7227
7239
  const map = /* @__PURE__ */ new Map();
@@ -8725,12 +8737,13 @@ window.__ModuleLoader__.load({
8725
8737
  * 单次 setRecords 合并全部结果,避免逐条往返读写整个 sidecar。
8726
8738
  * @author ddj 2026年08月25号
8727
8739
  * @param items 决策项数组(callId/scope/hunkIndex/decision)
8728
- * @returns Promise<{ok:number; fail:number}> 成功/失败计数
8740
+ * @returns Promise<{ok:number; fail:number; stale:number}> 成功/失败/已不存在计数
8729
8741
  */
8730
8742
  const actMany = (items) => {
8731
8743
  if (!items.length) return Promise.resolve({
8732
8744
  ok: 0,
8733
- fail: 0
8745
+ fail: 0,
8746
+ stale: 0
8734
8747
  });
8735
8748
  return rpc("edrv.decideBatch", {
8736
8749
  sessionId,
@@ -8740,30 +8753,46 @@ window.__ModuleLoader__.load({
8740
8753
  setError(res?.error ? String(res.error) : "批量处理失败");
8741
8754
  return {
8742
8755
  ok: 0,
8743
- fail: items.length
8756
+ fail: items.length,
8757
+ stale: 0
8744
8758
  };
8745
8759
  }
8746
8760
  let ok = 0;
8747
8761
  let fail = 0;
8762
+ let stale = 0;
8748
8763
  const next = {};
8749
8764
  for (const item of res.results) if (item && item.ok) {
8750
8765
  ok++;
8766
+ if (item.stale === true) stale++;
8751
8767
  if (item.record) next[item.callId] = item.record;
8752
8768
  } else fail++;
8753
8769
  if (Object.keys(next).length) setRecords((prev) => Object.assign({}, prev, next));
8754
8770
  return {
8755
8771
  ok,
8756
- fail
8772
+ fail,
8773
+ stale
8757
8774
  };
8758
8775
  }).catch((e) => {
8759
8776
  setError("批量处理异常:" + String(e));
8760
8777
  return {
8761
8778
  ok: 0,
8762
- fail: items.length
8779
+ fail: items.length,
8780
+ stale: 0
8763
8781
  };
8764
8782
  });
8765
8783
  };
8766
8784
  /**
8785
+ * 批量决策状态文案(含"差异已不存在于文件"提示)。
8786
+ * @author ddj 2026年09月15号
8787
+ * @param prefix 动作前缀(已采纳/已不采纳)
8788
+ * @param result 批量决策计数
8789
+ * @returns 状态栏文案
8790
+ */
8791
+ const decideStatus = (prefix, result) => {
8792
+ const text = prefix + result.ok + " 处差异" + (result.fail ? "," + result.fail + " 处失败" : "");
8793
+ return result.stale ? text + "(其中 " + result.stale + " 处已不存在于文件,未改动)" : text;
8794
+ };
8795
+ /**
8767
8796
  * 决策项构造(与单条 actHunk 的 scope 语义一致:create 记录走 call 作用域)。
8768
8797
  * @author ddj 2026年08月25号
8769
8798
  * @param r 差异区域/待处理项(callId/idx/create)
@@ -8777,27 +8806,27 @@ window.__ModuleLoader__.load({
8777
8806
  decision: reject ? "rejected" : "accepted"
8778
8807
  });
8779
8808
  const acceptFile = () => {
8780
- if (batchBusyRef.current || !pendingRegions.length) return;
8809
+ if (batchBusyRef.current || !decideRegions.length) return;
8781
8810
  batchBusyRef.current = true;
8782
- actMany(pendingRegions.map((r) => itemOf(r, false))).then(({ ok, fail }) => {
8811
+ actMany(decideRegions.map((r) => itemOf(r, false))).then((result) => {
8783
8812
  batchBusyRef.current = false;
8784
8813
  reloadFile(true);
8785
8814
  emitRefresh();
8786
- setStatus("已采纳 " + ok + " 处差异" + (fail ? "," + fail + " 处失败" : ""));
8787
- if (fail) setError(fail + " 处差异处理失败(可能已被后续修改影响),可刷新后重试");
8815
+ setStatus(decideStatus("已采纳 ", result));
8816
+ if (result.fail) setError(result.fail + " 处差异处理失败(可能已被后续修改影响),可刷新后重试");
8788
8817
  }).catch(() => {
8789
8818
  batchBusyRef.current = false;
8790
8819
  });
8791
8820
  };
8792
8821
  const undoFile = () => {
8793
- if (batchBusyRef.current || !pendingRegions.length) return;
8822
+ if (batchBusyRef.current || !decideRegions.length) return;
8794
8823
  batchBusyRef.current = true;
8795
- actMany([...pendingRegions].reverse().map((r) => itemOf(r, true))).then(({ ok, fail }) => {
8824
+ actMany([...decideRegions].reverse().map((r) => itemOf(r, true))).then((result) => {
8796
8825
  batchBusyRef.current = false;
8797
8826
  reloadFile(true);
8798
8827
  emitRefresh();
8799
- setStatus("已不采纳 " + ok + " 处差异" + (fail ? "," + fail + " 处失败" : ""));
8800
- if (fail) setError(fail + " 处差异处理失败(可能已被后续修改影响),可刷新后重试");
8828
+ setStatus(decideStatus("已不采纳 ", result));
8829
+ if (result.fail) setError(result.fail + " 处差异处理失败(可能已被后续修改影响),可刷新后重试");
8801
8830
  }).catch(() => {
8802
8831
  batchBusyRef.current = false;
8803
8832
  });
@@ -8826,12 +8855,12 @@ window.__ModuleLoader__.load({
8826
8855
  if (batchBusyRef.current || !allPending.length) return;
8827
8856
  batchBusyRef.current = true;
8828
8857
  const list = reject ? [...allPending].sort((a, b) => a.at < b.at ? 1 : a.at > b.at ? -1 : b.idx - a.idx) : allPending;
8829
- actMany(list.map((r) => itemOf(r, reject))).then(({ ok, fail }) => {
8858
+ actMany(list.map((r) => itemOf(r, reject))).then((result) => {
8830
8859
  batchBusyRef.current = false;
8831
8860
  reloadFile(true);
8832
8861
  emitRefresh();
8833
- setStatus((reject ? "已不采纳 " : "已采纳 ") + ok + " 处差异" + (fail ? "," + fail + " 处失败" : ""));
8834
- if (fail) setError(fail + " 处差异处理失败(可能已被后续修改影响),可刷新后重试");
8862
+ setStatus(decideStatus(reject ? "已不采纳 " : "已采纳 ", result));
8863
+ if (result.fail) setError(result.fail + " 处差异处理失败(可能已被后续修改影响),可刷新后重试");
8835
8864
  }).catch(() => {
8836
8865
  batchBusyRef.current = false;
8837
8866
  });
@@ -9668,6 +9697,7 @@ window.__ModuleLoader__.load({
9668
9697
  const [detailsOpen, setDetailsOpen] = react.default.useState(false);
9669
9698
  const detailsId = react.default.useId();
9670
9699
  const canAct = pendingRegions.length > 0;
9700
+ const canDecide = canDecideFile(pendingRegions.length, staleRegions.length);
9671
9701
  const base = String(activePath || "").split(/[\\/]/).pop() || "";
9672
9702
  if (mode === "chat" || mode === "editor-empty") return react.default.createElement("div", {
9673
9703
  className: "edrv-diffbar edrv-diffbar-dock",
@@ -9768,12 +9798,12 @@ window.__ModuleLoader__.load({
9768
9798
  }, base)), react.default.createElement("div", { className: "edrv-diffbar-actions" }, react.default.createElement("button", {
9769
9799
  className: "edrv-pill edrv-pill-keep",
9770
9800
  title: "采纳当前文件的全部差异",
9771
- disabled: !canAct,
9801
+ disabled: !canDecide,
9772
9802
  onClick: onAcceptFile
9773
9803
  }, "✓ Keep"), react.default.createElement("button", {
9774
9804
  className: "edrv-pill edrv-pill-undo",
9775
9805
  title: "不采纳当前文件的全部差异(回滚)",
9776
- disabled: !canAct,
9806
+ disabled: !canDecide,
9777
9807
  onClick: onUndoFile
9778
9808
  }, "↩ Undo"), react.default.createElement("button", {
9779
9809
  className: "edrv-pill edrv-pill-ghost edrv-diff-details-toggle",