dsh-recall-plugin 2.4.16 → 2.5.1

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/lib/config.js CHANGED
@@ -38,13 +38,16 @@ const Config = Schema.object({
38
38
  // issue #24:单文件上限挡不住「大量小文件」——下载目录 321 个 ≤100MB 文件
39
39
  // 合计 1.05GB 全部进快照。总量超限时**整体停用该工作区快照**而非截断:
40
40
  // 截断快照回退时,未纳入的文件会命中回退脚本的「当前有、目标无」删除侧。
41
- maxWorkspaceBytes: withVolatile(Schema.number().default(268435456).description("\u5355\u5DE5\u4F5C\u533A\u53EF\u7EB3\u5165\u5FEB\u7167\u7684\u6587\u4EF6\u603B\u91CF\u4E0A\u9650\uFF0C\u8D85\u8FC7\u5373\u505C\u7528\u8BE5\u5DE5\u4F5C\u533A\u5FEB\u7167\uFF1B0 \u8868\u793A\u4E0D\u9650\u5236")),
42
- scanBudgetMs: withVolatile(Schema.number().default(1e4).description("\u5FEB\u7167\u524D\u626B\u63CF\uFF08\u904D\u5386\u5DE5\u4F5C\u533A\u7EDF\u8BA1\u603B\u91CF\uFF09\u7684\u65F6\u95F4\u9884\u7B97\uFF0C\u8D85\u65F6\u5373\u505C\u7528\u672C\u6B21\u5FEB\u7167\uFF1B0 \u8868\u793A\u4E0D\u9650\u5236")),
41
+ maxWorkspaceBytes: withVolatile(Schema.number().default(268435456).description("\u5355\u5DE5\u4F5C\u533A\u53EF\u7EB3\u5165\u5FEB\u7167\u7684\u6587\u4EF6\u603B\u91CF\u4E0A\u9650\uFF0C\u53E3\u5F84\u4E0E git add \u4E00\u81F4\uFF08\u542B .gitignore\uFF09\uFF0C\u8D85\u8FC7\u5373\u505C\u7528\u8BE5\u5DE5\u4F5C\u533A\u5FEB\u7167\uFF1B0 \u8868\u793A\u4E0D\u9650\u5236")),
42
+ scanBudgetMs: withVolatile(Schema.number().default(1e4).description("\u5FEB\u7167\u524D\u7EDF\u8BA1\u7EB3\u5165\u603B\u91CF\u7684\u65F6\u95F4\u9884\u7B97\uFF0C\u8D85\u65F6\u5373\u505C\u7528\u672C\u6B21\u5FEB\u7167\uFF1B0 \u8868\u793A\u4E0D\u9650\u5236")),
43
43
  maxSnapshotsPerWorkspace: withVolatile(Schema.number().default(500).description("\u6BCF\u4E2A\u5DE5\u4F5C\u533A\u4FDD\u7559\u7684\u6700\u5927\u5FEB\u7167\u6570\uFF0C\u8D85\u9650\u5220\u9664\u6700\u65E7\u7684")),
44
44
  baseExcludes: withVolatile(Schema.array(Schema.string()).default(BASE_EXCLUDES).description("\u57FA\u7840\u6392\u9664\u8868\uFF08gitignore \u8BED\u6CD5\uFF0C\u4F18\u5148\u7EA7\u4F4E\u4E8E exclude.txt\uFF09")),
45
45
  refillDraft: withVolatile(Schema.boolean().default(true).description("\u64A4\u56DE\u540E\u628A\u88AB\u64A4\u56DE\u7684\u6D88\u606F\uFF08\u6587\u672C\u4E0E\u9644\u4EF6\uFF09\u56DE\u586B\u5230\u8F93\u5165\u6846")),
46
46
  snapshotEnabled: withVolatile(Schema.boolean().default(true).description("\u542F\u7528\u6D88\u606F\u5FEB\u7167\uFF08\u5173\u95ED\u540E\u4E0D\u518D\u65B0\u5EFA\uFF0C\u5DF2\u6709\u5FEB\u7167\u4ECD\u53EF\u64A4\u56DE\uFF09")),
47
47
  archiveOriginal: withVolatile(Schema.boolean().default(true).description("\u64A4\u56DE\u540E\u5F52\u6863\u539F\u4F1A\u8BDD\uFF08\u5173\u95ED\u540E\u539F\u4F1A\u8BDD\u4FDD\u7559\u5728\u5217\u8868\u4E2D\uFF09")),
48
+ // issue #26:编辑提交后自动发出改后的文本。关闭则退化为「只回填输入框」,
49
+ // 给「只想改稿、不立刻发」的用户留一条与撤回回填一致的出口
50
+ editSubmitsImmediately: withVolatile(Schema.boolean().default(true).description("\u300C\u7F16\u8F91\u5E76\u91CD\u53D1\u300D\u63D0\u4EA4\u540E\u81EA\u52A8\u53D1\u51FA\u6539\u540E\u7684\u6D88\u606F\uFF08\u5173\u95ED\u5219\u53EA\u56DE\u586B\u8F93\u5165\u6846\uFF09")),
48
51
  retentionDays: withVolatile(Schema.number().default(0).description("\u6309\u5929\u6570\u4FDD\u7559\u5FEB\u7167\uFF0C\u8D85\u671F\u81EA\u52A8\u5220\u9664\uFF1B0 \u8868\u793A\u4E0D\u542F\u7528")),
49
52
  // A4:界面语言。union 三值而不是自由字符串——非法配置在加载时响亮失败
50
53
  //(合规清单 #3);description 保持中文是 v1 明示限制:它由宿主官方设置
@@ -131,6 +134,7 @@ const DEFAULTS = {
131
134
  refillDraft: true,
132
135
  snapshotEnabled: true,
133
136
  archiveOriginal: true,
137
+ editSubmitsImmediately: true,
134
138
  retentionDays: 0,
135
139
  locale: "auto"
136
140
  };
@@ -152,10 +156,11 @@ function createConfig(raw) {
152
156
  const refillDraft = typeof cfg.refillDraft === "boolean" ? cfg.refillDraft : true;
153
157
  const snapshotEnabled = typeof cfg.snapshotEnabled === "boolean" ? cfg.snapshotEnabled : true;
154
158
  const archiveOriginal = typeof cfg.archiveOriginal === "boolean" ? cfg.archiveOriginal : true;
159
+ const editSubmitsImmediately = cfg.editSubmitsImmediately !== false;
155
160
  const rawDays = typeof cfg.retentionDays === "number" ? cfg.retentionDays : parseInt(String(cfg.retentionDays == null ? "" : cfg.retentionDays), 10);
156
161
  const retentionDays = Number.isFinite(rawDays) ? Math.max(0, rawDays) : 0;
157
162
  const locale = cfg.locale === "zh" || cfg.locale === "en" ? cfg.locale : "auto";
158
- return { gcSnaps, gcHours, maxFileBytes, maxWorkspaceBytes, scanBudgetMs, maxSnapshotsPerWorkspace, baseExcludes, refillDraft, snapshotEnabled, archiveOriginal, retentionDays, locale };
163
+ return { gcSnaps, gcHours, maxFileBytes, maxWorkspaceBytes, scanBudgetMs, maxSnapshotsPerWorkspace, baseExcludes, refillDraft, snapshotEnabled, archiveOriginal, editSubmitsImmediately, retentionDays, locale };
159
164
  }
160
165
  export {
161
166
  Config,
@@ -25,7 +25,7 @@ function createRoutesCore(deps) {
25
25
  notice.buildRootNotice = buildRootNotice(artifactSeg);
26
26
  }
27
27
  }
28
- return { ok: Boolean(root), root: root || null, notice, config: { refillDraft: cfg.refillDraft, archiveOriginal: cfg.archiveOriginal, locale: cfg.locale } };
28
+ return { ok: Boolean(root), root: root || null, notice, config: { refillDraft: cfg.refillDraft, archiveOriginal: cfg.archiveOriginal, editSubmitsImmediately: cfg.editSubmitsImmediately, locale: cfg.locale } };
29
29
  },
30
30
  "snapshot-info": async (args) => {
31
31
  const id = args && args.messageId ? String(args.messageId) : "";
@@ -287,6 +287,7 @@ function createRoutesManage(deps) {
287
287
  refillDraft: cfg.refillDraft,
288
288
  snapshotEnabled: cfg.snapshotEnabled,
289
289
  archiveOriginal: cfg.archiveOriginal,
290
+ editSubmitsImmediately: cfg.editSubmitsImmediately,
290
291
  retentionDays: cfg.retentionDays,
291
292
  // A4:界面语言偏好随 values 下发(设置卡片据此渲染下拉并即时切语言)
292
293
  locale: cfg.locale
@@ -325,6 +326,7 @@ function createRoutesManage(deps) {
325
326
  if (patch.refillDraft !== void 0) clean.refillDraft = Boolean(patch.refillDraft);
326
327
  if (patch.snapshotEnabled !== void 0) clean.snapshotEnabled = Boolean(patch.snapshotEnabled);
327
328
  if (patch.archiveOriginal !== void 0) clean.archiveOriginal = Boolean(patch.archiveOriginal);
329
+ if (patch.editSubmitsImmediately !== void 0) clean.editSubmitsImmediately = Boolean(patch.editSubmitsImmediately);
328
330
  if (patch.retentionDays !== void 0) {
329
331
  const n = Number(patch.retentionDays);
330
332
  if (!Number.isFinite(n) || n < 0) return { ok: false, code: E.RECALL_BAD_TYPE, message: "\u4FDD\u7559\u5929\u6570\u5FC5\u987B\u662F >= 0 \u7684\u6570\u5B57\uFF080 \u8868\u793A\u4E0D\u542F\u7528\uFF09" };
@@ -13,7 +13,9 @@ function dropGitlinksBlock() {
13
13
  return [
14
14
  `"$git" --git-dir="$g" ls-files -z --stage | while IFS= read -r -d '' e; do`,
15
15
  ' case "$e" in',
16
- ` 160000\\ *) p=\${e#*$'\\t'}; "$git" --literal-pathspecs --git-dir="$g" update-index --force-remove -- "$p" ;;`,
16
+ // --work-tree 不可省:影子仓库是 bare 仓库,裸 --git-dir 下 update-index 会
17
+ // fatal "this operation must be run in a work tree",set -e 直接终止整条快照
18
+ ` 160000\\ *) p=\${e#*$'\\t'}; "$git" --literal-pathspecs --git-dir="$g" --work-tree="$root" update-index --force-remove -- "$p" ;;`,
17
19
  " esac",
18
20
  "done"
19
21
  ].join("\n");
@@ -39,7 +41,9 @@ function oversizeBlock(maxBytes) {
39
41
  dirPruneArgsBlock(),
40
42
  'find "$root" "${oversize_prune[@]}" -type f -size +' + String(maxBytes || MAX_FILE_BYTES) + "c -print0 2>/dev/null | while IFS= read -r -d '' f; do",
41
43
  ` printf '%s\\0' "\${f#"$root"/}"`,
42
- 'done | xargs -0 "$git" --literal-pathspecs --git-dir="$g" update-index --force-remove -- 2>/dev/null || true'
44
+ // --work-tree 不可省:bare 影子仓库下裸 update-index fatal(被 || true 吞掉
45
+ // 后大文件会静默留在 index 里),maxFileBytes 的承诺会形同虚设
46
+ 'done | xargs -0 "$git" --literal-pathspecs --git-dir="$g" --work-tree="$root" update-index --force-remove -- 2>/dev/null || true'
43
47
  ].join("\n");
44
48
  }
45
49
  function limitScanBlock(maxBytes, fileMaxBytes, budgetMs) {
@@ -47,16 +51,27 @@ function limitScanBlock(maxBytes, fileMaxBytes, budgetMs) {
47
51
  const fileLimit = String(fileMaxBytes || MAX_FILE_BYTES);
48
52
  const budgetS = budgetMs > 0 ? String(Math.ceil(budgetMs / 1e3)) : "0";
49
53
  return [
50
- dirPruneArgsBlock(),
51
54
  "limit_start=$(date +%s)",
52
- `if find "$root" -maxdepth 0 -printf '' >/dev/null 2>&1; then`,
53
- ` limit_sizes=$(find "$root" "\${oversize_prune[@]}" -type f -printf '%s\\n' 2>/dev/null)`,
54
- "else",
55
- ' limit_sizes=$(find "$root" "${oversize_prune[@]}" -type f -exec stat -f%z {} + 2>/dev/null)',
55
+ 'limit_tmp="$g/limit-scan.$$"',
56
+ "limit_scan_ok=0",
57
+ // set -e:条件位置豁免,ls-files 失败不终止脚本——fail-open 只放行不判定
58
+ 'if "$git" -c core.quotePath=false --git-dir="$g" --work-tree="$root" ls-files -z -co --exclude-standard > "$limit_tmp" 2>/dev/null; then',
59
+ " limit_scan_ok=1",
60
+ "fi",
61
+ 'limit_sizes=""',
62
+ 'if [ "$limit_scan_ok" = 1 ] && [ -s "$limit_tmp" ]; then',
63
+ // ls-files 输出相对 root 的路径,而脚本 cwd 是宿主工作目录:必须 cd 进去再 stat
64
+ ` if find "$root" -maxdepth 0 -printf '' >/dev/null 2>&1; then`,
65
+ ` limit_sizes=$(cd "$root" && xargs -0 stat -c '%s %F' -- < "$limit_tmp" 2>/dev/null || true)`,
66
+ " else",
67
+ ` limit_sizes=$(cd "$root" && xargs -0 stat -f '%z %HT' -- < "$limit_tmp" 2>/dev/null || true)`,
68
+ " fi",
56
69
  "fi",
57
- // 口径 = 实际会进快照的字节:超过单文件上限的文件随后被 oversizeBlock
58
- // 移出 index,不计入总量(同 pwsh 侧,防一个大文件把干净项目误判超限)
59
- `limit_total=$(printf '%s\\n' "$limit_sizes" | awk -v lim=` + limit + " -v flim=" + fileLimit + ` '{ if ($1 <= flim) { s += $1; if (lim > 0 && s > lim) { print "OVER " s; exit } } } END { if (lim <= 0 || s <= lim) print s }')`,
70
+ 'rm -f "$limit_tmp"',
71
+ // 目录条目(嵌套仓库在 ls-files 里输出 `dir/`)不计入:add 侧同样不纳入它
72
+ // 的内容(gitlink 被剔除 / 无提交时 unable to index);越过单文件上限的也
73
+ // 不计入——oversizeBlock 随后会把它移出 index
74
+ `limit_total=$(printf '%s\\n' "$limit_sizes" | awk -v lim=` + limit + " -v flim=" + fileLimit + ` '{ if (tolower($0) ~ /directory/) next; if ($1 <= flim) { s += $1; if (lim > 0 && s > lim) { print "OVER " s; exit } } } END { if (lim <= 0 || s <= lim) print s }')`,
60
75
  "limit_elapsed=$(( $(date +%s) - limit_start ))",
61
76
  'case "$limit_total" in',
62
77
  ' OVER\\ *) echo "SNAP_LIMIT bytes ${limit_total#OVER } ' + limit + '"; exit 0 ;;',
@@ -86,7 +101,14 @@ function excludeSyncBlock(excludeFile, base) {
86
101
  'old_exc=$(cat "$exc" 2>/dev/null || true)',
87
102
  'if [ "$new_exc" != "$old_exc" ]; then',
88
103
  ` printf '%s\\n' "$new_exc" > "$exc"`,
89
- ' "$git" -c core.quotePath=false --literal-pathspecs --git-dir="$g" ls-files -i -c --exclude-from="$exc" -z 2>/dev/null | xargs -0 "$git" --literal-pathspecs --git-dir="$g" update-index --force-remove -- 2>/dev/null || true',
104
+ // 影子仓库是 bare:写 index 必须显式 --work-tree,否则 update-index fatal
105
+ // 并被 || true 吞成「排除对已跟踪条目从未生效」。ensureGitScript 也走本函数
106
+ // 但没有 root(建仓不遍历工作区),那时退回原调用(命中通常为空,fail-open)
107
+ ' if [ -n "${root:-}" ]; then',
108
+ ' "$git" -c core.quotePath=false --literal-pathspecs --git-dir="$g" ls-files -i -c --exclude-from="$exc" -z 2>/dev/null | xargs -0 "$git" --literal-pathspecs --git-dir="$g" --work-tree="$root" update-index --force-remove -- 2>/dev/null || true',
109
+ " else",
110
+ ' "$git" -c core.quotePath=false --literal-pathspecs --git-dir="$g" ls-files -i -c --exclude-from="$exc" -z 2>/dev/null | xargs -0 "$git" --literal-pathspecs --git-dir="$g" update-index --force-remove -- 2>/dev/null || true',
111
+ " fi",
90
112
  "fi"
91
113
  ].join("\n");
92
114
  }
@@ -13,7 +13,7 @@ function dropGitlinksBlock() {
13
13
  return [
14
14
  "& $git --git-dir=$g ls-files --stage | Where-Object { $_ -like '160000*' } | ForEach-Object {",
15
15
  ' $p = ($_ -split "`t")[1]',
16
- " & $git --literal-pathspecs --git-dir=$g update-index --force-remove -- $p",
16
+ " & $git --literal-pathspecs --git-dir=$g --work-tree=$root update-index --force-remove -- $p",
17
17
  "}"
18
18
  ].join("\n");
19
19
  }
@@ -80,7 +80,9 @@ function oversizeBlock(maxBytes) {
80
80
  "}",
81
81
  "for ($i = 0; $i -lt $oversizeRel.Count; $i += 100) {",
82
82
  " $batch = $oversizeRel.GetRange($i, [Math]::Min(100, $oversizeRel.Count - $i))",
83
- " & $git --literal-pathspecs --git-dir=$g update-index --force-remove -- $batch",
83
+ // --work-tree 不可省:bare 影子仓库下裸 update-index 会 fatal,pwsh 不抛
84
+ // → 大文件静默留在 index 里,maxFileBytes 的承诺形同虚设
85
+ " & $git --literal-pathspecs --git-dir=$g --work-tree=$root update-index --force-remove -- $batch",
84
86
  "}"
85
87
  ].join("\n");
86
88
  }
@@ -90,27 +92,31 @@ function limitScanBlock(maxBytes, fileMaxBytes, budgetMs) {
90
92
  const budget = budgetMs > 0 ? String(budgetMs) : "0";
91
93
  return [
92
94
  "$limitSw = [Diagnostics.Stopwatch]::StartNew()",
93
- dirSkipSetBlock("limitSkip"),
94
- "$limitStack = [System.Collections.Generic.Stack[string]]::new()",
95
- "$limitStack.Push($root)",
96
95
  "$limitBytes = [long]0",
97
96
  "$limitHit = ''",
98
- "while ($limitStack.Count -gt 0) {",
99
- " if (" + budget + " -gt 0 -and $limitSw.ElapsedMilliseconds -gt " + budget + ") { $limitHit = 'time'; break }",
100
- " $dir = $limitStack.Pop()",
101
- " try {",
102
- " $di = [System.IO.DirectoryInfo]::new($dir)",
97
+ "$limitRc = 0",
98
+ "$limitFiles = @()",
99
+ // PS 5.1:native stderr 在 EAP=Stop 下会被包成 ErrorRecord 直接抛(pwsh 7
100
+ // 不抛),一条 warning 就能让整条快照挂掉——与下方 add 段同款临时降级
101
+ "$limitEap = $ErrorActionPreference",
102
+ "$ErrorActionPreference = 'Continue'",
103
+ "try {",
104
+ // -z:路径含换行也不分裂(实测 PS 5.1/7 的 @() 都保留 NUL)
105
+ " $limitFiles = @(((& $git -c core.quotePath=false --git-dir=$g --work-tree=$root ls-files -z -co --exclude-standard 2>$null) -join '').Split([char]0))",
106
+ " $limitRc = $LASTEXITCODE",
107
+ "} finally { $ErrorActionPreference = $limitEap }",
108
+ "if ($limitRc -eq 0) {",
109
+ " foreach ($limitRel in $limitFiles) {",
110
+ // 两道守卫吸收两类异常条目:5.1 的 Split 会留尾部空串;目录条目(嵌套仓库
111
+ // 输出 `dir/`)的 Length 为空或抛——两者都不该计入(add 侧同样不纳入)
112
+ " if (-not $limitRel) { continue }",
113
+ " if (" + budget + " -gt 0 -and $limitSw.ElapsedMilliseconds -gt " + budget + ") { $limitHit = 'time'; break }",
114
+ " try { $limitLen = [System.IO.FileInfo]::new($root + '/' + $limitRel).Length } catch { $limitLen = [long]0 }",
103
115
  // 口径 = 实际会进快照的字节:超过单文件上限的文件随后被 oversizeBlock
104
116
  // 移出 index,不该计入总量(否则一个 300MB 视频就能把干净项目误判超限)
105
- " foreach ($f in $di.EnumerateFiles()) { if ($f.Length -le " + fileLimit + ") { $limitBytes += $f.Length } }",
106
- " if (" + limit + " -gt 0 -and $limitBytes -gt " + limit + ") { $limitHit = 'bytes' }",
107
- " if ($limitHit) { break }",
108
- " foreach ($d in $di.EnumerateDirectories()) {",
109
- " if ($limitSkip.Contains($d.Name)) { continue }",
110
- " if (($d.Attributes -band [System.IO.FileAttributes]::ReparsePoint) -ne 0) { continue }",
111
- " $limitStack.Push($d.FullName)",
112
- " }",
113
- " } catch {}",
117
+ " if ($limitLen -gt 0 -and $limitLen -le " + fileLimit + ") { $limitBytes += $limitLen }",
118
+ " if (" + limit + " -gt 0 -and $limitBytes -gt " + limit + ") { $limitHit = 'bytes'; break }",
119
+ " }",
114
120
  "}",
115
121
  "if ($limitHit -eq 'bytes') { Write-Output ('SNAP_LIMIT bytes ' + $limitBytes + ' ' + " + limit + "); exit 0 }",
116
122
  "if ($limitHit -eq 'time') { Write-Output ('SNAP_LIMIT time ' + $limitSw.ElapsedMilliseconds + ' ' + " + budget + "); exit 0 }"
@@ -146,7 +152,14 @@ function excludeSyncBlock(excludeFile, base) {
146
152
  " } else {",
147
153
  " for ($i = 0; $i -lt $hit.Count; $i += 100) {",
148
154
  " $batch = @($hit[$i..([Math]::Min($i + 99, $hit.Count - 1))])",
149
- " & $git --literal-pathspecs --git-dir=$g update-index --force-remove -- $batch",
155
+ // 影子仓库是 bare:写 index 必须显式 --work-tree,否则 update-index fatal。
156
+ // ensureGitScript 也走本函数但没有 $root(建仓不遍历工作区)——那时保留
157
+ // 原样调用,命中列表通常为空,最坏是清理静默跳过(fail-open)
158
+ " if ($root) {",
159
+ " & $git --literal-pathspecs --git-dir=$g --work-tree=$root update-index --force-remove -- $batch",
160
+ " } else {",
161
+ " & $git --literal-pathspecs --git-dir=$g update-index --force-remove -- $batch",
162
+ " }",
150
163
  " }",
151
164
  " }",
152
165
  "}"
package/lib/snapshots.js CHANGED
@@ -27,7 +27,7 @@ function bytesText(bytes) {
27
27
  }
28
28
  function buildSnapshotLimitNotice(limit) {
29
29
  if (limit.kind === "bytes") {
30
- return "\u8BE5\u5DE5\u4F5C\u533A\u53EF\u7EB3\u5165\u5FEB\u7167\u7684\u6587\u4EF6\u603B\u91CF\u8D85\u8FC7\u4E0A\u9650\uFF08\u7EA6 " + bytesText(limit.value) + " / " + bytesText(limit.limit) + "\uFF09\uFF0C\u5DF2\u505C\u7528\u5FEB\u7167\uFF1B\u53EF\u8C03\u5927\u300C\u5DE5\u4F5C\u533A\u603B\u91CF\u4E0A\u9650\u300D\u6216\u8865\u5145\u6392\u9664\u8868\u540E\u81EA\u52A8\u6062\u590D";
30
+ return "\u8BE5\u5DE5\u4F5C\u533A\u53EF\u7EB3\u5165\u5FEB\u7167\u7684\u6587\u4EF6\u603B\u91CF\u8D85\u8FC7\u4E0A\u9650\uFF08\u7EA6 " + bytesText(limit.value) + " / " + bytesText(limit.limit) + "\uFF0C\u5DF2\u6309 .gitignore \u4E0E\u6392\u9664\u8868\u8FC7\u6EE4\uFF09\uFF0C\u5DF2\u505C\u7528\u5FEB\u7167\uFF1B\u53EF\u8C03\u5927\u300C\u5DE5\u4F5C\u533A\u603B\u91CF\u4E0A\u9650\u300D\u6216\u8865\u5145\u6392\u9664\u8868\u540E\u81EA\u52A8\u6062\u590D";
31
31
  }
32
32
  return "\u5FEB\u7167\u524D\u7684\u6587\u4EF6\u626B\u63CF\u8D85\u8FC7\u65F6\u95F4\u9884\u7B97\uFF08\u7EA6 " + Math.max(1, Math.round(limit.value / 1e3)) + " \u79D2 / " + Math.max(1, Math.round(limit.limit / 1e3)) + " \u79D2\uFF09\uFF0C\u5DF2\u505C\u7528\u5FEB\u7167\uFF1B\u53EF\u8C03\u5927\u300C\u626B\u63CF\u65F6\u95F4\u9884\u7B97\u300D\u6216\u8865\u5145\u6392\u9664\u8868\u540E\u81EA\u52A8\u6062\u590D";
33
33
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-recall-plugin",
3
- "version": "2.4.16",
3
+ "version": "2.5.1",
4
4
  "description": "在 DSH 中撤回自己发过的消息:工作区文件与对话历史一起回到那条消息发出之前,消息的文本与附件自动放回输入框,改完即可重发。文件走独立影子 git 快照(不碰项目自身的 git),对话走官方 sessions.fork,原会话归档可找回。",
5
5
  "icon": "assets/icon.svg",
6
6
  "type": "module",
@@ -74,7 +74,8 @@
74
74
  "0.2.1-alpha.4": "compatible",
75
75
  "0.2.1-alpha.5": "compatible",
76
76
  "0.2.1-rc.1": "compatible",
77
- "0.2.1-rc.2": "compatible"
77
+ "0.2.1-rc.2": "compatible",
78
+ "0.2.1-rc.3": "compatible"
78
79
  }
79
80
  }
80
81
  },