dsh-deepseek-web-login 0.6.19 → 0.6.22
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 +67 -1
- package/lib/client.js +27 -4
- package/lib/client.js.map +1 -1
- package/lib/index.js +440 -41
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
本项目大致遵循语义化版本;日期为本地时间。
|
|
4
|
+
|
|
5
|
+
## 0.6.22 — 2026-10-01
|
|
6
|
+
|
|
7
|
+
**修复:一个窗口聊两句、网页端多出三个会话;以及选「不删」反而触发一次批量删除。**
|
|
8
|
+
|
|
9
|
+
两个独立 bug。这次不再是推测——判据来自实机证据:会话 `13fc4478` 的原始事件日志
|
|
10
|
+
(哪一轮发了什么、有几个 step)+ `~/.dsh/web-login/sessions-in-use.json` 的实际内容
|
|
11
|
+
(11 条记录:8 条 `queued` / 3 条 `slot`,时间点与前者的 turn/step 逐一对应)。
|
|
12
|
+
|
|
13
|
+
### ① 重开链强制换新会话 ⇒ 每个回合多一个网页端会话
|
|
14
|
+
|
|
15
|
+
- `needsFreshSession` 的旧判据:链式模式下「要发根消息 + 会话是复用来的」就**换一个新会话**
|
|
16
|
+
(0.6.10 引入,当时的假设是"重开链是异常路径,代价可接受")。
|
|
17
|
+
- 实测该假设不成立:DSH 每一轮都会重新生成**替换式**的运行时注入
|
|
18
|
+
(原话:`Current runtime context. This snapshot supersedes earlier runtime-context snapshots.`),
|
|
19
|
+
链的 entries 于是不再是本轮 entries 的严格前缀 ⇒ `decideFeed` 必然 `restart('not-appended')`
|
|
20
|
+
⇒ parent=null ⇒ 换新会话、旧会话交回清理。实测时间线:12:50:36 建会话①、12:51:07 建②、
|
|
21
|
+
12:51:13 建③ —— 一个窗口、两句对话。
|
|
22
|
+
- 现在**默认不换**:重开链就在当前会话里发根消息,一个窗口始终只用一个网页端会话。
|
|
23
|
+
- 保留开关:面板「上下文」页 →「重开链时换新会话」,或 `gate.json` 的
|
|
24
|
+
`freshSessionOnRestart`(缺省 `false`)。打开即恢复 0.6.10 的行为。
|
|
25
|
+
|
|
26
|
+
### ② 在设置页选「不删」,反而立刻触发一次批量删除
|
|
27
|
+
|
|
28
|
+
- `createSessionCleaner().configure()` 对 `mode === 'keep'` 调用的是 `flush()`,
|
|
29
|
+
而 `flush()` → `doFlush()` → `deleteChunk()` 是**真的发 DELETE 请求**——
|
|
30
|
+
用户的意图与执行结果完全相反。
|
|
31
|
+
- 改为「放弃队列」:清空待删队列、撤掉定时器,并**逐条发 `abandoned`** 让宿主把
|
|
32
|
+
`session-journal` 里的欠账销掉。少了销账这一步,下次启动只要清理模式不是 `keep`,
|
|
33
|
+
补扫又会把这些会话删掉(等于"不删"只生效到本次进程结束)。
|
|
34
|
+
- 宿主的销账分支(`deleted` / `abandoned`)移到 `journalEnabled` 判断**之前** ——
|
|
35
|
+
`keep` 模式下 `journalEnabled` 为 `false`,否则记录根本摘不掉。
|
|
36
|
+
|
|
37
|
+
### 验证
|
|
38
|
+
|
|
39
|
+
- `tsc --noEmit`、`npm run test`(60/60 用例文件)、`check-smoke`、`check-bundle` 全部通过
|
|
40
|
+
- 新增 5 条用例,其中 2 条是**行为断言**(★:切成「不删」后一个 `DELETE` 都不许发出;
|
|
41
|
+
放弃删除必须逐条报 `abandoned`)
|
|
42
|
+
- 两条修复各自做了**变异反向验证**:把源码改回 bug ⇒ 对应用例变红、`rc=1`
|
|
43
|
+
- 首版用例的默认值断言曾与常量脱钩(`reset` 里写死 `false`),导致"改默认值"的变异跑不出红;
|
|
44
|
+
已把默认值收敛成单一来源 `DEFAULT_FRESH_SESSION_ON_RESTART`
|
|
45
|
+
|
|
46
|
+
## 0.6.21 — 2026-10-01
|
|
47
|
+
|
|
48
|
+
**修复:传输层诊断测试未跟随浏览器代理。**
|
|
49
|
+
|
|
50
|
+
- 面板显示「通过系统 Edge/Chrome 进程代理」时,「测试传输层」按钮仍只检查 `electron.net.fetch`,
|
|
51
|
+
导致实际已生效的浏览器代理被误判为不可用。
|
|
52
|
+
- `transport.ts` 新增 `currentEffectiveFetch()`,记录并暴露当前实际生效的 fetch 种类
|
|
53
|
+
(`node` / `electron` / `browser`)。
|
|
54
|
+
- `net-diagnostics.ts` 改为用当前生效的 fetch 做探测,测试结果区分 `electron.net.fetch` 与
|
|
55
|
+
`浏览器代理`。
|
|
56
|
+
- 当实际生效为 Node fetch 时,错误提示改为「未启用 Chrome 网络栈」。
|
|
57
|
+
|
|
58
|
+
## 0.6.20 — 2026-10-01
|
|
59
|
+
|
|
60
|
+
**浏览器代理传输层:官方 DSH 桌面端也能走真实 Chrome 指纹。**
|
|
61
|
+
|
|
62
|
+
- 新增 `src/browser-transport.ts`:当 `electron.net.fetch` 不可用时,启动系统里的 Edge/Chrome 进程
|
|
63
|
+
(headless + 独立 profile),通过 CDP `Runtime.addBinding` 把请求代理给浏览器的 `fetch()`。
|
|
64
|
+
- 请求实际从浏览器网络栈发出,TLS/HTTP2 指纹与真实浏览器一致;响应通过 binding 分块传回 Node,
|
|
65
|
+
再包装成标准 `Response`(含 ReadableStream)。
|
|
66
|
+
- `transport.ts` 自动 fallback:electron.net.fetch → 系统浏览器代理 → Node fetch。
|
|
67
|
+
- 设置页提示更新:走浏览器代理时显示「通过系统 Edge/Chrome 进程代理」;无浏览器时才降级 Node。
|
|
68
|
+
- 新增回归用例 `tests/check-browser-transport.mjs`;保留 `DSH_NO_BROWSER_TRANSPORT=1` 测试开关。
|
|
69
|
+
- 传输层文案保持「Chrome 网络栈」(0.6.19)。
|
|
4
70
|
|
|
5
71
|
## 0.6.19 — 2026-10-01
|
|
6
72
|
|
package/lib/client.js
CHANGED
|
@@ -2201,6 +2201,24 @@ background:var(--bg2);white-space:pre-wrap;font-size:12px}
|
|
|
2201
2201
|
contextCard.append(contextStatus);
|
|
2202
2202
|
const contextHintText = el("p", "dsw-hint", "");
|
|
2203
2203
|
contextCard.append(contextHintText);
|
|
2204
|
+
const freshRow = el("div", "dsw-gate-row");
|
|
2205
|
+
const freshLabel = el("label", "dsw-switch");
|
|
2206
|
+
const freshInput = el("input", "dsw-switch-input");
|
|
2207
|
+
freshInput.type = "checkbox";
|
|
2208
|
+
freshLabel.append(freshInput, el("span", "dsw-switch-track"), el("span", void 0, "重开链时换新会话"));
|
|
2209
|
+
freshRow.append(freshLabel);
|
|
2210
|
+
contextCard.append(freshRow);
|
|
2211
|
+
const freshHint = el("p", "dsw-hint", "");
|
|
2212
|
+
contextCard.append(freshHint);
|
|
2213
|
+
const paintFreshSession = () => {
|
|
2214
|
+
freshHint.textContent = freshInput.checked ? "开:每次重开链都新建一个网页端会话、旧的弃用 —— 上下文最干净,代价是网页端会多出会话。" : "默认关:一个窗口始终只用一个网页端会话。DSH 每轮都会刷新运行时注入,投喂链几乎每个回合都会重开 ——关掉才能保证\"聊十句也只有一个会话\"。";
|
|
2215
|
+
};
|
|
2216
|
+
freshInput.checked = false;
|
|
2217
|
+
paintFreshSession();
|
|
2218
|
+
freshInput.addEventListener("change", () => {
|
|
2219
|
+
paintFreshSession();
|
|
2220
|
+
saveGate({ freshSessionOnRestart: freshInput.checked });
|
|
2221
|
+
});
|
|
2204
2222
|
const contextMsg = createMsgNode();
|
|
2205
2223
|
contextCard.append(contextMsg.node);
|
|
2206
2224
|
contextPane.append(contextCard);
|
|
@@ -2304,12 +2322,15 @@ background:var(--bg2);white-space:pre-wrap;font-size:12px}
|
|
|
2304
2322
|
const requested = String(info.requested ?? info.effective ?? "chromium");
|
|
2305
2323
|
const effective = String(info.effective ?? requested);
|
|
2306
2324
|
for (const key of Object.keys(transportBtns)) transportBtns[key].classList.toggle("active", key === requested);
|
|
2307
|
-
const available = info.chromiumAvailable !== false;
|
|
2325
|
+
const available = info.chromiumAvailable !== false || info.browserAvailable !== false;
|
|
2308
2326
|
transportBtns.chromium.disabled = !available;
|
|
2309
|
-
transportBtns.chromium.title = available ? "" : "
|
|
2327
|
+
transportBtns.chromium.title = available ? "" : "本环境找不到 Edge/Chrome,也没有 electron.net.fetch,不支持 Chrome 网络栈";
|
|
2310
2328
|
const parts = [effective === "chromium" ? "实际生效:Chrome 网络栈" : "实际生效:Node fetch"];
|
|
2311
|
-
if (info.degraded) parts.push("配置要求 Chrome
|
|
2312
|
-
if (effective === "chromium")
|
|
2329
|
+
if (info.degraded) parts.push("配置要求 Chrome,但本环境找不到 Edge/Chrome 也没有 electron.net.fetch,已降级为 Node");
|
|
2330
|
+
if (effective === "chromium") {
|
|
2331
|
+
if (info.viaBrowserProxy) parts.push("通过系统 Edge/Chrome 进程代理");
|
|
2332
|
+
else parts.push("cipher 列表哈希与 Chrome 一致、ALPN 走 h2");
|
|
2333
|
+
}
|
|
2313
2334
|
transportHint.textContent = parts.join(" · ");
|
|
2314
2335
|
transportProxyHint.textContent = String(info.hint ?? "");
|
|
2315
2336
|
};
|
|
@@ -2446,6 +2467,8 @@ background:var(--bg2);white-space:pre-wrap;font-size:12px}
|
|
|
2446
2467
|
serialInput.checked = g.serialToolCalls === false;
|
|
2447
2468
|
paintSerialTools();
|
|
2448
2469
|
autoReloginInput.checked = g.autoRelogin === true;
|
|
2470
|
+
freshInput.checked = g.freshSessionOnRestart === true;
|
|
2471
|
+
paintFreshSession();
|
|
2449
2472
|
const mode = g.cleanup?.mode ?? "deferred";
|
|
2450
2473
|
for (const key of Object.keys(cleanupBtns)) cleanupBtns[key].classList.toggle("active", key === mode);
|
|
2451
2474
|
const showRanges = mode === "deferred";
|