@michengai/dsh-archive-manager 1.0.19 → 1.0.20

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/CHANGELOG.md CHANGED
@@ -6,6 +6,13 @@ Published release notes are retained below; new versions are added without remov
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 1.0.20 - 2026-10-16
10
+
11
+ - Permanently deleting an archived session no longer fails just because the host cannot read a damaged transcript. The session files and archive record are removed, and a leftover list entry disappears without restarting DSH.
12
+ - If removal cannot be confirmed, the deletion stays incomplete and the archive mark is kept. It is not reported as deleted.
13
+ - Delete errors stay in the host's own wording. English and Russian screens no longer mix in a Chinese diagnosis.
14
+ - The archive confirmation window closes as soon as processing finishes, instead of staying open while the session list refreshes.
15
+
9
16
  ## 1.0.19 - 2026-10-15
10
17
 
11
18
  - Keep JSONL latest-host mounting compatible with both Cordis `apply` (alpha.3+) and the older default constructor export; restore archived-path protection without rebinding the original `sessionPath`/`candidateMatches` references.
@@ -6,6 +6,13 @@
6
6
 
7
7
  ## 未发布
8
8
 
9
+ ## 1.0.20 - 2026-10-16
10
+
11
+ - 永久删除已归档会话时,不再因为宿主读不出损坏的转录就失败。会话文件和归档记录会被清掉;列表里残留的条目不用重启 DSH 也会消失。
12
+ - 无法确认已经删掉时,删除仍算未完成,归档标记会保留,不会报成已删除。
13
+ - 删除失败时保留宿主自己的说法。英文和俄文界面不再混进中文说明。
14
+ - 归档确认窗口在处理完成后立刻关闭,不再等会话列表刷新。
15
+
9
16
  ## 1.0.19 - 2026-10-15
10
17
 
11
18
  - 最新宿主 JSONL 夹具同时兼容 Cordis `apply`(alpha.3+)与旧版 default 构造导出;归档路径保护卸下时还原原始 `sessionPath`/`candidateMatches` 引用。
@@ -208,11 +208,25 @@ function classifySessionError(error) {
208
208
  ["legacy-source", /unclassified message source/],
209
209
  ["missing", /ENOENT|不存在|not found/i],
210
210
  ["permission", /EACCES|EPERM|permission/i],
211
- ["corrupt", /corrupt|JSON|incomplete|truncat|损坏/i]
211
+ ["corrupt", /corrupt|JSON|incomplete|truncat|损坏|SessionFormatError/i]
212
212
  ];
213
213
  const rawCode = errorCode(error);
214
+ const name = error && typeof error === "object" && "name" in error ? String(error.name ?? "") : "";
214
215
  const explicit = typeof rawCode === "string" ? codes[rawCode] ?? rawCode : "";
215
- const code = Object.hasOwn(descriptions, explicit) ? explicit : patterns.find(([, pattern]) => pattern.test(message))?.[0] ?? "unknown";
216
+ if (Object.hasOwn(descriptions, explicit)) {
217
+ const [reason2, advice2] = descriptions[explicit];
218
+ return { code: explicit, reason: reason2, advice: advice2 };
219
+ }
220
+ const emptyToolCall = /requires toolCallId matching its tool source|tool call id requires a nonempty string/i;
221
+ if (emptyToolCall.test(message)) {
222
+ return {
223
+ code: "corrupt",
224
+ reason: "\u65E5\u5FD7\u5C3E\u90E8\u6709\u672A\u95ED\u5408\u7684\u5DE5\u5177\u8C03\u7528\uFF0C\u4E14 toolCallId \u4E3A\u7A7A",
225
+ advice: "\u4FDD\u7559\u73B0\u6709\u65E5\u5FD7\uFF0C\u68C0\u67E5\u78C1\u76D8\u548C\u539F\u59CB\u6587\u4EF6\uFF1B\u4E0D\u81EA\u52A8\u622A\u65AD\u6216\u6539\u5199\u65E5\u5FD7\u3002"
226
+ };
227
+ }
228
+ const namedCorrupt = name === "SessionFormatError" || name === "SessionPersistenceCorruptionError" ? "corrupt" : void 0;
229
+ const code = namedCorrupt ?? patterns.find(([, pattern]) => pattern.test(message))?.[0] ?? "unknown";
216
230
  const [reason, advice] = descriptions[code];
217
231
  return { code, reason, advice };
218
232
  }