dsh-deepseek-web-login 0.6.17 → 0.6.18
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 +24 -0
- package/lib/index.js +17 -8
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
本项目遵循大致语义化版本;日期为本地时间。
|
|
4
4
|
|
|
5
|
+
## 0.6.18 — 2026-10-01
|
|
6
|
+
|
|
7
|
+
**修会话爆炸:token 刷新/内部请求不再冲掉 chat 的网页端会话。**
|
|
8
|
+
|
|
9
|
+
用户现场:链式投喂下,一个窗口聊了几句后网页端突然多出几个新会话,上一句的会话也没了;
|
|
10
|
+
刷新后只剩一个。根因有两个,合在一起触发:
|
|
11
|
+
|
|
12
|
+
1. **`accountKey` 用 `token|cookie` 当账号身份** —— token 每 2 小时左右就会刷新(自动/手动重登),
|
|
13
|
+
刷新后插件认为"换了账号",旧网页端会话被退役,投喂链也断了。
|
|
14
|
+
2. **内部请求(`session-title`、`compaction` 等)也传 `promptParts` 走链式** —— 这些请求的条目
|
|
15
|
+
和 chat 的链不匹配,触发了「历史不是严格追加 → 重开链 → 强制换新会话」,于是每个标题/压缩
|
|
16
|
+
请求都把当前 chat 会话冲掉,旧的删、新的建。
|
|
17
|
+
|
|
18
|
+
### 改动
|
|
19
|
+
|
|
20
|
+
- `webapi.ts`:`accountKey` 优先用服务端返回的 `user.id` 当稳定身份;没有 `user.id` 时才回退到
|
|
21
|
+
`token|cookie`(兼容手动粘 token 的老记录)。
|
|
22
|
+
- `adapter.ts`:只有用户可见的 `chat` 才把 `promptParts` 传下去;`session-title` / `compaction`
|
|
23
|
+
等内部调用走全量,不再抢 chat 的链。
|
|
24
|
+
- `context-feed.ts` / `webapi.ts`:没有 `promptParts` 的请求不触发「强制换新会话」,也不会因为
|
|
25
|
+
没 ready 而把 chat 的链删掉。
|
|
26
|
+
- 回归用例:`check-session-reuse` +2(token 刷新稳定性/回退)、`check-context-chain` +1、
|
|
27
|
+
`check-context-feed` +1,全部反向验证。
|
|
28
|
+
|
|
5
29
|
## 0.6.17 — 2026-10-01
|
|
6
30
|
|
|
7
31
|
**增量投喂不再重发「模型上一句回答」(用户反馈:完全没必要)。**
|
package/lib/index.js
CHANGED
|
@@ -3384,8 +3384,9 @@ function isAssistantTranscriptEntry(entry) {
|
|
|
3384
3384
|
* 重新开始",那就该配一个干净会话(旧会话交回给它自己的清理)。
|
|
3385
3385
|
* 本来就是新会话(`reused === false`)时**不重复换**,否则每轮都白建一个。
|
|
3386
3386
|
*/
|
|
3387
|
-
function needsFreshSession(feed, reused, mode) {
|
|
3387
|
+
function needsFreshSession(feed, reused, mode, hasPromptParts = true) {
|
|
3388
3388
|
if (mode !== "chained") return false;
|
|
3389
|
+
if (!hasPromptParts) return false;
|
|
3389
3390
|
return feed.parentMessageId === null && reused;
|
|
3390
3391
|
}
|
|
3391
3392
|
/**
|
|
@@ -5034,9 +5035,16 @@ function contextChainInfo() {
|
|
|
5034
5035
|
...lastRetireReason ? { lastRetire: lastRetireReason } : {}
|
|
5035
5036
|
};
|
|
5036
5037
|
}
|
|
5037
|
-
/** 凭证摘要:只用来判断「是不是同一个账号」。不做安全用途、不落日志。
|
|
5038
|
+
/** 凭证摘要:只用来判断「是不是同一个账号」。不做安全用途、不落日志。
|
|
5039
|
+
*
|
|
5040
|
+
* 🔴 0.6.18:改用服务端返回的 `user.id` 当稳定身份。旧实现把 `token|cookie` 当身份,
|
|
5041
|
+
* 而 token 每 2 小时左右就会刷新(自动/手动重登)⇒ 刷新后插件认为是「换了账号」,
|
|
5042
|
+
* 旧网页端会话被退役删除、投喂链也断了,用户看到的就是「聊了几句会话就没了、下一句又建新会话」。
|
|
5043
|
+
* `user.id` 是账号在服务端的真实身份,稳定不变;没有时才回退到 token+cookie。
|
|
5044
|
+
*/
|
|
5038
5045
|
function accountKey(auth) {
|
|
5039
|
-
const
|
|
5046
|
+
const userId = auth?.user?.id;
|
|
5047
|
+
const raw = typeof userId === "string" && userId ? `uid:${userId}` : `${auth?.token ?? ""}|${auth?.cookie ?? ""}`;
|
|
5040
5048
|
let hash = 2166136261;
|
|
5041
5049
|
for (let i = 0; i < raw.length; i += 1) {
|
|
5042
5050
|
hash ^= raw.charCodeAt(i);
|
|
@@ -5188,7 +5196,7 @@ async function openCompletion(auth, params, signal, transport) {
|
|
|
5188
5196
|
...contextChains.get(slotKey) ? { chain: contextChains.get(slotKey) } : {}
|
|
5189
5197
|
});
|
|
5190
5198
|
let feed = planFeed(lease.sessionId, lease.reused);
|
|
5191
|
-
if (needsFreshSession(feed, lease.reused, currentContextMode())) {
|
|
5199
|
+
if (needsFreshSession(feed, lease.reused, currentContextMode(), params.promptParts !== void 0)) {
|
|
5192
5200
|
const reason = feed.reason;
|
|
5193
5201
|
lease = await leaseSession(auth, signal, transport, params.sessionReuseTurns ?? 20, params.onDeleteSession, true, slotKey);
|
|
5194
5202
|
feed = {
|
|
@@ -5470,7 +5478,7 @@ async function* streamWebCompletion(auth, params, transport = defaultTransport)
|
|
|
5470
5478
|
parentId: responseMessageId
|
|
5471
5479
|
});
|
|
5472
5480
|
lastChainKey = slotKey;
|
|
5473
|
-
} else if (sentChainKey !== void 0) {
|
|
5481
|
+
} else if (sentChainKey !== void 0 && params.promptParts !== void 0) {
|
|
5474
5482
|
contextChains.delete(sentChainKey);
|
|
5475
5483
|
if (lastChainKey === sentChainKey) lastChainKey = void 0;
|
|
5476
5484
|
}
|
|
@@ -6603,15 +6611,16 @@ function createAdapter(deps) {
|
|
|
6603
6611
|
finishReason = void 0;
|
|
6604
6612
|
textLenAtRoundStart = textBlock?.text?.length ?? 0;
|
|
6605
6613
|
roundStartedAt = Date.now();
|
|
6614
|
+
const chatLike = allowsAutoContinue(options?.purpose);
|
|
6606
6615
|
try {
|
|
6607
6616
|
for await (const event of runStream(auth, {
|
|
6608
6617
|
prompt: currentPrompt,
|
|
6609
6618
|
canFailover: deps.canFailover,
|
|
6610
|
-
promptParts: {
|
|
6619
|
+
...chatLike ? { promptParts: {
|
|
6611
6620
|
head: promptParts.head,
|
|
6612
6621
|
entries: promptParts.entries,
|
|
6613
6622
|
maxChars: deps.config.maxPromptChars ?? 4e5
|
|
6614
|
-
},
|
|
6623
|
+
} } : {},
|
|
6615
6624
|
onContextFeed: (report) => {
|
|
6616
6625
|
logger?.info?.(report.reason === "chained" ? `deepseek-web: 上下文投喂=链式:本轮只发增量 ${report.promptChars} 字(历史由服务端维护${report.echoDropped > 0 ? `,另略过 ${report.echoDropped} 条模型回声` : ""})` : report.reason === "mode-full" ? "deepseek-web: 上下文投喂=每轮全量:重发完整 prompt" : `deepseek-web: 链式投喂退回全量重发(原因=${report.reason})`);
|
|
6617
6626
|
},
|
|
@@ -9560,7 +9569,7 @@ async function checkForUpdate(current, fetchImpl) {
|
|
|
9560
9569
|
* 兜底常量与 package.json 的一致性由 `tests/check-smoke.mjs` 守着,不会漂。
|
|
9561
9570
|
*/
|
|
9562
9571
|
/** 与 package.json 保持一致的兜底版本(由测试保证不会漂)。 */
|
|
9563
|
-
const FALLBACK_VERSION = "0.6.
|
|
9572
|
+
const FALLBACK_VERSION = "0.6.18";
|
|
9564
9573
|
let cached;
|
|
9565
9574
|
/** 本插件版本(如 `0.1.26`)。 */
|
|
9566
9575
|
function pluginVersion() {
|