dsh-deepseek-web-login 0.7.4 → 0.7.5
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 +47 -0
- package/lib/index.js +24 -4
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,53 @@
|
|
|
2
2
|
|
|
3
3
|
本项目大致遵循语义化版本;日期为本地时间。
|
|
4
4
|
|
|
5
|
+
## 0.7.5 — 2026-10-10
|
|
6
|
+
|
|
7
|
+
**修好 0.6.43 那个从未生效的修复:退出 DSH 会把持久化状态自己抹掉。**
|
|
8
|
+
|
|
9
|
+
### 根因
|
|
10
|
+
|
|
11
|
+
`disposeSessionReuse()` 是**卸载钩子**(`index.ts` 的 `ctx.effect(() => () => …)`),
|
|
12
|
+
它`clear()` 内存之后**紧接着 `persistResumeState()`** ⇒ **把空态写回了文件**。
|
|
13
|
+
|
|
14
|
+
⇒ **每次退出 DSH,`resume-state.json` 都被自己清空** ⇒ 下次启动 `restoreResumeState()` 读回空。
|
|
15
|
+
**0.6.43/0.7.1 的"重启后仍能续上同一会话"在真实使用下等于没生效。**
|
|
16
|
+
|
|
17
|
+
症状:同一对话线被迫建新会话 + 网页端出现「修改 / 重新生成」分叉(实测 27 万字符全量重发)。
|
|
18
|
+
|
|
19
|
+
### 修法
|
|
20
|
+
|
|
21
|
+
`persistResumeState(opts?: { persist?: boolean })` —— **退出 / 重置语义**的调用点传 `false`:
|
|
22
|
+
|
|
23
|
+
- `disposeSessionReuse()`(卸载钩子,最要紧)
|
|
24
|
+
- `resetSessionReuse()`
|
|
25
|
+
- `resetContextChain()`
|
|
26
|
+
|
|
27
|
+
其余 8 处调用点都是**真实增删改**(入栈、出栈、链更新、链删除、会话退役),**照旧落盘**。
|
|
28
|
+
|
|
29
|
+
### 为什么之前一直是绿的
|
|
30
|
+
|
|
31
|
+
- `check-resume-after-restart` 只测**「进程 → 进程」**,**不经过卸载钩子**;
|
|
32
|
+
- `check-bundle` 守的是"落盘点存在",**不守"落盘的内容对不对"**。
|
|
33
|
+
|
|
34
|
+
⚠️ **加了持久化就必须测「退出 → 启动」这个生命周期边界。**
|
|
35
|
+
|
|
36
|
+
### 新增守卫
|
|
37
|
+
|
|
38
|
+
`tests/check-persist-lifecycle.mjs`(3 条)—— 先用 `writeResumeStateForTest` 造出**非空**落盘态,
|
|
39
|
+
再调三个清空函数,断言**文件内容没被写空**。变异验证:三处改回 `persistResumeState()` ⇒ 三条一起红。
|
|
40
|
+
|
|
41
|
+
`check-bundle` 新增一条守**卸载钩子那个调用点真的存在**(断"没被调用")。
|
|
42
|
+
|
|
43
|
+
⚠️ 这条守卫的首版**恒真**:`slice().includes('disposeSessionReuse()')` 命中了同一段里那行
|
|
44
|
+
**注释**「① `disposeSessionReuse()` 把复用槽里的会话…」⇒ 删掉真实调用后仍为真。
|
|
45
|
+
⇒ 改成**按行判**(`line.trim() === 'disposeSessionReuse()'`)才抓住。
|
|
46
|
+
**这是「断言会被注释引用污染」的又一例,与 MEMORY纪律③同源。**
|
|
47
|
+
|
|
48
|
+
### 验证
|
|
49
|
+
|
|
50
|
+
`tsc` / build / 产物 / 新守卫 3 / 产物新增那条 / 外部审查 8 / `check-resume-after-restart` / 隔离 全过。
|
|
51
|
+
|
|
5
52
|
## 0.7.4 — 2026-10-10
|
|
6
53
|
|
|
7
54
|
**收窄 0.7.3 的 `--no-sandbox`:只给 headless 传输层,登录窗口保持 sandbox。**
|
package/lib/index.js
CHANGED
|
@@ -6628,7 +6628,27 @@ function persistStatePath() {
|
|
|
6628
6628
|
return join(webLoginDir(), PERSIST_FILE);
|
|
6629
6629
|
}
|
|
6630
6630
|
/** 把当前内存状态写盘。**永不抛** —— 落盘失败不该让正常请求失败。 */
|
|
6631
|
-
|
|
6631
|
+
/**
|
|
6632
|
+
* 把当前内存状态写盘。**永不抛** —— 落盘失败不该让正常请求失败。
|
|
6633
|
+
*
|
|
6634
|
+
* 🔴 2026-10-10(0.7.5)`opts.persist: false`:**退出 / 重置语义**的调用点要用它。
|
|
6635
|
+
*
|
|
6636
|
+
* ## 为什么需要这个开关
|
|
6637
|
+
*
|
|
6638
|
+
* 0.6.43 给会话槽与链加了落盘,好让"重启后仍能续上同一会话"。但三个**清空**函数
|
|
6639
|
+
* (`resetContextChain` / `disposeSessionReuse` / `resetSessionReuse`)在 `clear()` 之后
|
|
6640
|
+
* **紧接着调persistResumeState()** ⇒ **把空态写回了文件**。
|
|
6641
|
+
*
|
|
6642
|
+
* 其中 `disposeSessionReuse()` 是**卸载钩子**(`index.ts` 的 `ctx.effect(() => () => …��`)
|
|
6643
|
+
* ⇒ **每次退出 DSH,持久化的状态都被自己抹掉** ⇒ 重启后 `restoreResumeState()` 读回空。
|
|
6644
|
+
* 症状:网页端同一对话线被迫建新会话 + 出现「修改 / 重新生成」分叉(实测 27 万字符全量重发)。
|
|
6645
|
+
*
|
|
6646
|
+
* 之所以长期没被发现:`check-resume-after-restart` 只测**「进程 → 进程」**,
|
|
6647
|
+
* **不经过卸载钩子**;`check-bundle` 守的是"落盘点存在",**不守"落盘的内容对不对"**。
|
|
6648
|
+
* ⚠️ **加了持久化就必须测「退出 → 启动」这个生命周期边界。**
|
|
6649
|
+
*/
|
|
6650
|
+
function persistResumeState(opts) {
|
|
6651
|
+
if (opts?.persist === false) return;
|
|
6632
6652
|
try {
|
|
6633
6653
|
const chains = [...contextChains.entries()].map(([key, s]) => ({
|
|
6634
6654
|
key,
|
|
@@ -6775,7 +6795,7 @@ function resetContextChain() {
|
|
|
6775
6795
|
contextChains.clear();
|
|
6776
6796
|
lastChainKey = void 0;
|
|
6777
6797
|
lastFeedReason = void 0;
|
|
6778
|
-
persistResumeState();
|
|
6798
|
+
persistResumeState({ persist: false });
|
|
6779
6799
|
}
|
|
6780
6800
|
/** 给状态页看:当前链式投喂是否真的在跑(没用链式就返回 undefined)。 */
|
|
6781
6801
|
function contextChainInfo() {
|
|
@@ -6911,7 +6931,7 @@ function disposeSessionReuse() {
|
|
|
6911
6931
|
reuseSlots.clear();
|
|
6912
6932
|
contextChains.clear();
|
|
6913
6933
|
lastChainKey = void 0;
|
|
6914
|
-
persistResumeState();
|
|
6934
|
+
persistResumeState({ persist: false });
|
|
6915
6935
|
sentRefIdsBySession.clear();
|
|
6916
6936
|
if (slots.length === 0) return void 0;
|
|
6917
6937
|
for (const slot of slots) try {
|
|
@@ -10935,7 +10955,7 @@ async function checkForUpdate(current, fetchImpl) {
|
|
|
10935
10955
|
* 兜底常量与 package.json 的一致性由 `tests/check-smoke.mjs` 守着,不会漂。
|
|
10936
10956
|
*/
|
|
10937
10957
|
/** 与 package.json 保持一致的兜底版本(由测试保证不会漂)。 */
|
|
10938
|
-
const FALLBACK_VERSION = "0.7.
|
|
10958
|
+
const FALLBACK_VERSION = "0.7.5";
|
|
10939
10959
|
let cached;
|
|
10940
10960
|
/** 本插件版本(如 `0.1.26`)。 */
|
|
10941
10961
|
function pluginVersion() {
|