@eddyskywalker/dsh-chatgpt-subscription 0.10.20 → 0.10.21
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
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- **修复思维坍塌保护每次触发都把当前会话写成坏记录**(用户报告:DSH 弹出「是否修复插件根因」,并指控本插件)。
|
|
6
|
+
- **根因**:`reasoning-collapse-guard` 用**手写字面量** `{ role: 'user', content: [...] }` 构造续跑消息(`src/host/reasoning-collapse-guard/index.ts` 的 `createResumeMessage`),既没有 `id` 也没有 `source`。DSH 在 `session.append` 里经 `assertMessageEventShape` 校验每条入站消息,缺 `id` 抛 `lacks an identified message`、缺 `source` 抛 `has invalid source`——**两个都会抛**。
|
|
7
|
+
- **为什么后果严重**:这个 steer 是在守卫**已经 `cancel` 之后**、于微任务里发出的。抛错发生时,坍塌已经中止、inbox 已保留,而这一轮直接以一条 splice 违规收场,模型什么也没回答——用户看到的正是「提示·等待回答」停在半截。
|
|
8
|
+
- **为什么当初写成字面量**:注释写的是「不引入绑定版本的 message 工厂,以便在每个 DSH 代际上都能加载」。这是当年**真实**的约束,不是惰性——但它用错了地方:`createUserMessage` 自 0.1.2-alpha.5 起就存在(已按 tag 核对),而 `id` / `source` 的要求是硬性的,工厂恰是唯一能同时满足两者的东西。
|
|
9
|
+
- **修法**:改用 `createUserMessage()`,并带上本插件自己已声明的 `dsh-chatgpt-subscription` source kind、`form: 'notice'` 与一行摘要。这样续跑消息既带真实身份与出处(不再冒充人工回合),也在 0.1.2-alpha.5 → 0.2.0-rc.2 全区间可用。
|
|
10
|
+
- **测试**:新增一条**复现原故障**的用例——不只断言消息长什么样,而是把守卫实际 steer 出来的消息喂给 DSH 真正的 `adoptSessionEvent`,断言它被接受。已验证该用例**承重**:临时换回修复前的字面量后,它立即以 `lacks an identified message` 失败(3 failed / 28 passed)。
|
|
11
|
+
- **验证**:`npx tsc -b --force` 与 test tsconfig 均 0 错误;全量 **2142 passed** / 7 skipped,**0 失败**;`npm run build` 与 `npm pack --dry-run` 干净。
|
|
12
|
+
- **边界**:已写入的历史坏记录不会被本次修复追溯修改——它们在用户报告的会话里已存在,需要 DSH 侧的一次修复或从修复点前分叉。
|
|
13
|
+
|
|
5
14
|
- **修复输出上限被当作固定预留,导致自动压缩失效**(#30 / #31);仅修改本插件,不要求修改 DSH。
|
|
6
15
|
- Kimi / MiniMax 不再上报动态预算为 `defaultMaxTokens`;仍在发送阶段按原公式计算并夹取线上 cap,显式请求上限(含摘要请求)仍优先,不引入固定 32K/64K 截断。
|
|
7
16
|
- 其余六条线路按 DSH 默认压缩策略检查固定预留:安全的默认值保持原样,不安全的省略。覆盖实时目录与窗口覆盖;Command Code 的 Kimi-K2.6 / Grok 4.5 / Grok 4.6、WorkBuddy 的 deepseek-v3-2-volc 默认配置受益。Claude、Antigravity、Codex 内置默认配置未发现同类失败,仍增加小窗口保护;Ollama 检查实时窗口。
|
package/lib/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import http, { createServer } from "node:http";
|
|
|
13
13
|
import { WebError } from "@deepseek-ai/dsh-web";
|
|
14
14
|
import { lookup } from "node:dns/promises";
|
|
15
15
|
import { isIP } from "node:net";
|
|
16
|
-
import { createUserMessage } from "@deepseek-ai/dsh-llm/message";
|
|
16
|
+
import { boundContextSummary, createUserMessage } from "@deepseek-ai/dsh-llm/message";
|
|
17
17
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
18
18
|
import { ProxyAgent, fetch as fetch$1 } from "undici";
|
|
19
19
|
import * as SettingsModule from "@deepseek-ai/dsh-settings";
|
|
@@ -39413,6 +39413,38 @@ function installRelayProbe(ctx, options) {
|
|
|
39413
39413
|
}
|
|
39414
39414
|
//#endregion
|
|
39415
39415
|
//#region src/host/reasoning-collapse-guard/index.ts
|
|
39416
|
+
/**
|
|
39417
|
+
* Reasoning-collapse guard.
|
|
39418
|
+
*
|
|
39419
|
+
* A long reasoning stream can degenerate into repetition: it cycles through a
|
|
39420
|
+
* handful of short phrases ("Let me call. Go. Calling. Go.") without emitting a
|
|
39421
|
+
* tool call or concluding anything, and runs until the output-token ceiling
|
|
39422
|
+
* truncates it. One archived session burned 128,000 output tokens that way and
|
|
39423
|
+
* returned an empty answer.
|
|
39424
|
+
*
|
|
39425
|
+
* The guard scores n-gram uniqueness over a trailing window of reasoning text.
|
|
39426
|
+
* Healthy deliberation keeps nearly every n-gram unique and scores near zero; a
|
|
39427
|
+
* degenerate stream scores near one. On a hit it stops yielding chunks, so the
|
|
39428
|
+
* in-flight request ends, and lets the turn resume on a fresh step.
|
|
39429
|
+
*
|
|
39430
|
+
* Seam choice: the guard wraps `llm/stream`, not `agent/assistant-stream`.
|
|
39431
|
+
* `agent/assistant-stream` is emit-mode — it can observe but cannot stop a
|
|
39432
|
+
* stream — and it does not exist before harness 0.1.5, which would make the
|
|
39433
|
+
* guard a silent no-op on every generation this plugin supports below that.
|
|
39434
|
+
* `llm/stream` is a waterfall whose `(options, next) => AsyncIterable<StreamChunk>`
|
|
39435
|
+
* signature is byte-identical from 0.1.2-alpha.5 through 0.2.0-rc.1, and
|
|
39436
|
+
* returning early from the listener is what actually ends the stream.
|
|
39437
|
+
*
|
|
39438
|
+
* The guard subscribes to that waterfall and never reassigns `ctx.llm.stream`.
|
|
39439
|
+
* The harness publishes `stream` as a one-argument method that enters the
|
|
39440
|
+
* waterfall itself, so a property rewrite carrying a second `next` parameter
|
|
39441
|
+
* breaks every caller dispatching it as a method, and misses the prepared
|
|
39442
|
+
* call that skips the published method entirely.
|
|
39443
|
+
*
|
|
39444
|
+
* The guard rewrites nothing and appends nothing to the aborted attempt. Its
|
|
39445
|
+
* only model-visible input is the single resume message it queues afterwards,
|
|
39446
|
+
* on a fresh turn.
|
|
39447
|
+
*/
|
|
39416
39448
|
const DEFAULT_GUARD_OPTIONS = {
|
|
39417
39449
|
windowChars: 4096,
|
|
39418
39450
|
minWindowChars: 1500,
|
|
@@ -39482,17 +39514,35 @@ function createBreakerState() {
|
|
|
39482
39514
|
};
|
|
39483
39515
|
}
|
|
39484
39516
|
/**
|
|
39485
|
-
* The resume message
|
|
39486
|
-
*
|
|
39517
|
+
* The resume message the guard queues onto the kept inbox.
|
|
39518
|
+
*
|
|
39519
|
+
* It is built with the harness message factory and carries this package's own
|
|
39520
|
+
* source kind, because the harness rejects a message that is not fully
|
|
39521
|
+
* identified: a steer payload with no `id` is refused by
|
|
39522
|
+
* `assertMessageEventShape` (`session event … lacks an identified message`)
|
|
39523
|
+
* and one with no `source` by the same check (`… has invalid source`). Either
|
|
39524
|
+
* refusal is thrown from `session.append` at the very moment the guard's
|
|
39525
|
+
* microtask steers — after the abort has already been taken — so the failure
|
|
39526
|
+
* surfaced as a repairable-splice violation, the attempt was already cancelled,
|
|
39527
|
+
* and the turn ended with the user told nothing.
|
|
39528
|
+
*
|
|
39529
|
+
* `createUserMessage` is available on every supported generation, and the
|
|
39530
|
+
* `dsh-chatgpt-subscription` kind is this package's own entry in the
|
|
39531
|
+
* merge-extensible `MessageSourceMap`, so the resume carries real provenance
|
|
39532
|
+
* instead of impersonating a human turn.
|
|
39487
39533
|
*/
|
|
39488
39534
|
function createResumeMessage(text) {
|
|
39489
|
-
return {
|
|
39490
|
-
role: "user",
|
|
39535
|
+
return createUserMessage({
|
|
39491
39536
|
content: [{
|
|
39492
39537
|
type: "text",
|
|
39493
39538
|
text
|
|
39494
|
-
}]
|
|
39495
|
-
|
|
39539
|
+
}],
|
|
39540
|
+
source: {
|
|
39541
|
+
kind: PLUGIN_MESSAGE_SOURCE_KIND,
|
|
39542
|
+
form: "notice",
|
|
39543
|
+
summary: boundContextSummary("Reasoning collapsed; the attempt was stopped and resumed.")
|
|
39544
|
+
}
|
|
39545
|
+
});
|
|
39496
39546
|
}
|
|
39497
39547
|
function appendWindow(current, addition, limit) {
|
|
39498
39548
|
const combined = current + addition;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/host/reasoning-collapse-guard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/host/reasoning-collapse-guard/index.ts"],"names":[],"mappings":"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"}
|