@eddyskywalker/dsh-chatgpt-subscription 0.17.0 → 0.18.0
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 +40 -1
- package/README.md +3 -2
- package/lib/index.js +2828 -2508
- package/lib/types/host/antigravity/mapper.d.ts.map +1 -1
- package/lib/types/host/claude/mapper.d.ts.map +1 -1
- package/lib/types/host/command-code/mapper.d.ts.map +1 -1
- package/lib/types/host/common/request-images.d.ts +22 -2
- package/lib/types/host/common/request-images.d.ts.map +1 -1
- package/lib/types/host/kimi-code/adapter.d.ts.map +1 -1
- package/lib/types/host/kimi-code/mapper.d.ts +16 -1
- package/lib/types/host/kimi-code/mapper.d.ts.map +1 -1
- package/lib/types/host/kimi-code/types.d.ts +32 -0
- package/lib/types/host/kimi-code/types.d.ts.map +1 -1
- package/lib/types/host/minimax-code/adapter.d.ts +11 -0
- package/lib/types/host/minimax-code/adapter.d.ts.map +1 -1
- package/lib/types/host/minimax-code/client.d.ts.map +1 -1
- package/lib/types/host/workbuddy/mapper.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.18.0 - 2026-10-11
|
|
6
|
+
|
|
7
|
+
- **[MiniMax Code] 额度耗尽后不换号,而且把「限流」判成了「欠费」**
|
|
8
|
+
- **这条线路是唯一一条有号池却完全没有号池行为的线路。** 全包共 7 条线路(codex / claude / kimi-code / command-code / ollama / workbuddy / antigravity)都在非 2xx 的 429 上 `markCooldown` 并 `hasAnotherAvailableAccount(tried) → continue`;MiniMax 的 `src/host/minimax-code/` 全目录**零次** `markCooldown` 调用,`getEffectiveCredential(undefined, …)` 的 `excludeIds` 恒为空。于是某一个账号的 Token Plan 跑光之后,**后面每一个请求都继续由它来服务**——号池选它、被拒、再选它,没有任何一处在学习「它已经被拒过」。
|
|
9
|
+
- **结果是用户看不到换号,只看到额度耗尽。** 冷却机制本身是好的(`isEligible` 是纯时间比较,到期自动恢复),问题只在于从不写入。
|
|
10
|
+
- **识别层把普通限流判成了终局欠费。** 旧表里 `/exceeded/i` / `/quota/i` / `/balance/i` 是**裸词**,于是 `{"errorCode":1002,"errorReason":"rate_limit_exceeded"}` 这种最标准的限流信封被判成 `PROVIDER_ERROR` / `retryable:false` ——**本该由 DSH 有界退避重试的请求直接硬失败**。现在收紧为短语并补上本服务实际使用的中文措辞(余额/额度/配额 不足|耗尽|用尽、请充值、欠费、超出额度),且刻意**不**收录裸的「限制」「上限」,因为「请求超过频率限制」是标准限流句,必须继续保持可重试。
|
|
11
|
+
- **`summarizeFailureBody` 不认 `base_resp.status_msg`。** 那正是本线路在配额、Files API、签到三处都在解析的信封,用户此前会被展示一整个原始 JSON,而它唯一的内容就是那句话。
|
|
12
|
+
- **现在与兄弟线路同形**:新增 `accountScoped` 分类字段(沿用 kimi-code 的字段名与语义),429 冷却后在同一轮内换号重试;轮换循环按轮重建凭据、超大媒体上传与请求体,因此重放出来的请求绝不会指向另一个账号上传的文件 id(`uploadOversizedMedia` 把 access token 与 account key 一起交给 Files API,这是本线路独有的真实耦合)。
|
|
13
|
+
- **403 形态的额度耗尽一并处理,且不与凭据类 403 混淆。** 判别顺序是「先跑额度表、再落到凭据分支」,并且**状态码是外层条件**——任何 401 无论 body 写什么都进不了冷却分支,否则一个坏 token 会把整个号池走一遍。凭据提示语改为按**分类**挂载,额度耗尽的 403 不会再顺带甩一句 `sha256:…` 去怪那枚刚续期过的 token。
|
|
14
|
+
- **额度型 403 不再白花一次强制续期。** 这是上一版行为里最贵的一处:`renewCredential` 对「窗口已耗尽」毫无帮助,而对原生账号(凭据就是桌面端自己的 `auth.json`,池内 adopted never destroyed)那次续期会**把一对新令牌写回用户的桌面端文件**。现在有号池且 body 命中额度表时直接交给号池分支。**无号池路径刻意不跳过**:那里续期推进的是插件自己的凭据文件,且最终抛出的 detail 来自重放后的响应,跳过会改掉用户看到的文案。
|
|
15
|
+
- **401/403 不写 `markAuthFailed`,而且这是有证据的结论。** 适配器永远不会分类一个没先续期过的 401/403;能走到号池分支的必然是刚轮换出来的新令牌仍被拒。而「凭据不可用」早有两条更可靠的写入路径(`refreshFailureStatus` 在令牌端点最终拒绝时写 `authStatus`,`authRejectedReason` 另有免写入的排除)。在请求阶段补写反而制造**不可自愈的假阳性**:续期成功时新令牌对已经写进桌面端 `auth.json`,于是 `healStaleAuthFailures` 的四个条件一个都不满足——一次瞬时 403 会把正在使用的桌面账号**永久**标成「需要重新登录」,理由还是错的。现状已用测试钉住。
|
|
16
|
+
- 测试:新增 `test/minimax-code-429-cooldown.test.ts`(28 例),核心断言是「**一次** `adapter.stream()` 调用内,第一个账号 429 额度耗尽 → 第二个账号给出答案」,即 `['Bearer at-1', 'Bearer at-2']` 的鉴权顺序 + 调用方拿到 `text-delta` 而非异常。另覆盖:额度型 403 换号且 `tokenCalls === 0`、凭据型 401/403 **不冷却不轮换**(含单账号池与双账号池)、400/5xx 不轮换、原生桌面账号不被标记也不被冷却、in-band 429 只冷却、无号池路径逐字不变、以及「额度判决不会因为 body 被读两次而退化成凭据判决」。承重已用变异测试验证(禁用新门 → 2 红;去掉 body 复用 → 4 红,报错正是 `expected 'INVALID_CREDENTIAL' to be 'PROVIDER_ERROR'`)。
|
|
17
|
+
- 验证:`npm run typecheck` 0 错误;全量 `npm test` **3013 passed / 7 skipped, 0 failed**(较 0.17.1 的 2985 增 28 例,基线 2994 增 19 例)。未改共享内核、UI、DTO、路由。
|
|
18
|
+
- **未一并处理的**:① 无号池的额度型 403 仍会多花一次续期(上一段说明的取舍);② in-band(流式事件)的账号级 429 只能冷却、不能换号——响应体已经开着读了一半,结构上换不了,这是 7 条线路的共同限制,不是本线路独有。
|
|
19
|
+
## 0.17.1 - 2026-10-10
|
|
20
|
+
|
|
21
|
+
- **[Kimi Code] 请求体超限时,「还有图可丢吗」的判定与计量脱节,兜底一次都没跑([#51](https://github.com/Aa728848/dsh-chatgpt-subscription/issues/51))**
|
|
22
|
+
- **`requestHasSendableImage()` 只扫消息顶层,不递归 `tool-result`。** 同文件的另外三个兄弟函数全部递归——`collectImageRefs`、`collectRequestImagePayloads`(其注释明写 *RECURSION IS NOT OPTIONAL*)、`replaceOldestRequestImages`。于是对「图片全部来自工具结果」的请求,计量数得出 N 张图,判定恒返回 `false`。
|
|
23
|
+
- **后果不是「丢错图」,而是「一张都没丢」。** `kimi-code/adapter.ts` 的 body-fit 循环从 `attempt = 0` 起算,第一轮就短路,直接 `assertRequestBodyFits` 抛 `PROVIDER_ERROR`,唯一的丢图入口从未执行;`MAX_BODY_FIT_ATTEMPTS = 64` 形同虚设。报告方的现场只超限 **1494 字节**,丢一张约 150 KB 的图即可解决。混合会话同样中招:顶层图被丢光后,tool-result 里剩下的图一张不动,然后报错说「会先丢最旧的图」。
|
|
24
|
+
- **报错文案同时说了反话。** `oversizedBodyMessage` 的 remedy 按字节构成判定(`imageBytes >= otherBytes`),于是文案写着 “Older images are omitted first”,而实际一张都没丢。讽刺的是同文件的 `requestBodyBreakdown` 走的是全递归的 `walkJson`——**报错里的图片字节数看得见那些图,决定要不要继续丢图的门禁看不见。**
|
|
25
|
+
- **修复:把判定改成计量的定义式复用。** `requestHasSendableImage(options, images)` 现在就是 `requestImagePayloadLengths(options, images).length > 0`。手写第五遍递归也能修好这一例,但那条路保留了「同一条递归规则被抄多遍、下次再漏一遍」的结构性风险;复用定义让两者**按构造**不可能再分叉。
|
|
26
|
+
- **顺带统一了同一路径上的第二处口径错配(独立缺陷)。** `dropOldestImagesUntilFits` 里 `requestImagePayloadLengths(baseline, resolved)` 带 images 映射,`countOmitted` 里两次调用**不带**,`replaceOldestRequestImages` 的跳过判断也**不带**。三处只在 `unavailable`(读不出来的图)上分叉:不带映射时它回落 `base64Length(attachment.bytes)` 被当作「有载荷」,于是 `alreadyDropped` 虚高、`slice` 提前掏空、`additional` 算成 0,循环空转到 64 轮才抛错。现在三处统一传入同一个 `images`,`replaceOldestRequestImages` 新增可选形参。**只改计数端是不够的**:替换端若不同步改,`lengths[N]` 与「第 N 个可替换块」仍然错位。
|
|
27
|
+
- **附带效果**:`unavailable` 图现在会被判定为「不是可发送的图」,这类请求因此**立即 fail fast**,而不是白白重建 65 次几 MB 的请求体。
|
|
28
|
+
- 测试:`test/kimi-code-body-fit.test.ts` 新增 5 例——不变量(嵌套图、**丢图之前**判定必须与计量一致)、超限请求丢一张即可恢复、顶层图仍被看见(防修复被推到反方向)、`unavailable` 图不算作可丢(防过度递归)、替换名额必须花在真正带字节的图上。**承重已验证**:`git stash push -- src/host/common/request-images.ts src/host/kimi-code/adapter.ts` 后实测 **2 failed**(`expected false to be true`、``expected ['shot'] to deeply equal ['broken']``),还原后全过。
|
|
29
|
+
- 既有两条断言(`:143` 顶层图 `true`、`:153` 丢图后 `false`)**逐字未改仍然成立**——它们此前就与修复后的实现同值,只是从未覆盖真正出问题的那个状态。
|
|
30
|
+
- 验证:`tsc -b --pretty false` 与 `tsc -p test/tsconfig.json` 均 0 错误;全量 `npm test` **2961 passed / 7 skipped, 0 failed**(较基线增 5 例)。
|
|
31
|
+
- **未一并处理的**(与 0.13.2 记下的同一批):claude / command-code / workbuddy / antigravity 四条线路的计量与替换仍只扫顶层,工具结果里的图对它们的图片预算系统性失明;它们没有布尔门,不会本地抛错,表现为静默超预算后被上游 413/400 拒绝。codex 干净(在构造后的 input 上测量),minimax-code 干净(复用共享递归实现)。
|
|
32
|
+
|
|
33
|
+
- **[Kimi Code] 四条线路的图片预算让工具结果里的图「隐形」,以及字节上限缺出口 —— 补完 [#51](https://github.com/Aa728848/dsh-chatgpt-subscription/issues/51) 的遗留项**
|
|
34
|
+
- **状态 A 换了一条路存活。** 310590b 关掉的是「`tool-result` 里的图对门禁不可见」那一个实例;但 `dropOldestImagesUntilFits` 在「剩余图片总字节 < 超限缺口」时算出 `additional = 0` 并**原样返回**,调用方无法区分「成功了」与「没进展」,于是下一轮重建出**完全相同**的 body,空转到 `attempt > 64` 才抛出——期间连续构建 65 次几 MB 的请求体。实测可达:图片 1.6 MB + 文本 1.5 MB + schema 0.7 MB = 3.8 MB,缺口 1.7 MB > 图片 1.6 MB。
|
|
35
|
+
- **无进展检测。** 该函数改为返回 `{ options, dropped }`,`dropped === 0` 时立即停止并带着上下文抛错,不再消耗 attempt 预算重建一个不可能改变的请求。
|
|
36
|
+
- **报错文案从两态改为三态。** 判据从「字节构成猜测」换成「循环实际做了什么」:①**有图可丢但丢了也补不上缺口** → 明确说明剩下的图比缺口小,省略全部也装不下(不再声称「Older images are omitted first」);②**图已全部省略仍超限** → 报出已省略的张数;③**本来就没有图** → 直接排除删图这个无效动作。`BodyFitContext` 是可选第三参,**不传时逐字沿用原文案**,现有 14 条断言一条未改仍通过。
|
|
37
|
+
- **kimi-code 的字节上限补上环境变量出口**,`DSH_KIMI_CODE_MAX_BODY_BYTES` / `DSH_KIMI_CODE_MAX_IMAGE_BYTES`,与 MiniMax / Codex 两条线对齐(resolver 逐字同构:trim → 空串回落 → 非正有限数回落 → floor)。**视频上限不加出口**:三条线对称(minimax 同样是裸常量、codex 无视频),且一个变量管两档会让按 2 MB 场景设的值顺手压垮 64 MiB 视频档。共享常量 `common/request-images.ts` 的值与默认参数**未动**——那 8 处无参调用仍依赖它。
|
|
38
|
+
- **claude / command-code / workbuddy / antigravity 四条线路的工具结果图片重新进入预算。** 四条各自持有私有副本(预算数字不同、缩放策略不同、attachment seam 不同),实测**不能**合并到共享实现:合并会同时替换四条线路的度量口径、缩放策略与取消语义,且有两处行为变化**不会让任何现有用例变红**(用例都不传 images 映射,走 `images === undefined` 分支)——那是最危险的一类。因此逐条把度量和替换改为递归,**零测试期望值变化**。
|
|
39
|
+
- 顺带记录一处**刻意保留**的不一致:claude 的 `countRequestImages`(claude/mapper.ts:885-894)早已递归,而同文件的 `collectRequestImageBytes` 此前不递归——这正是本 bug 的**第五次**复制。统一它会让 `requestImageEdgeLimit` 不再把 `unavailable` 的图计入,而现有测试钉住了「刻意过度计数」的语义(低上限永远不会导致拒绝),故不动。
|
|
40
|
+
- 测试:新增 `test/tool-result-image-budget.test.ts`(13 例,`describe.each` 覆盖四条线路的「计量」「替换名额顺序」「装得下时不动」)、`test/kimi-code-body-limits.test.ts`(6 例,出口生效 / 非法值回落矩阵 / 默认值即 2,097,152 与 1,500,000)、`test/kimi-code-body-fit.test.ts` +4 例(三态文案各一条 + 不传参数时逐字不变);`test/kimi-code-adapter.test.ts` +1 例(适配器级「无进展即停止」,此前 `KimiCodeAdapter` 的 `options.attachments` 在测试中**从未被注入过**,那段 body-fit 循环零端到端覆盖)。`buildAdapter` 因此新增 `fetchFn` / `attachments` 两个可选参数。
|
|
41
|
+
- **承重已验证**:`git stash push -- ` 七个源文件后实测 **18 failed**(三态文案 3、无进展 1、四线路递归 9、环境出口 5),还原后全过。
|
|
42
|
+
- 验证:`npm run typecheck` 0 错误;全量 `npm test` **2985 passed / 7 skipped, 0 failed**(较 310590b 的 2961 增 24 例);`npm run build` 干净。
|
|
43
|
+
- **未一并处理的**:`/compact` 的 “could not produce a useful summary” 与真实原因不符。已复核——真实原因**已经落盘**在 `compaction/end.error`,宿主 `ManualCompactionError` 自己也带着 `message` 与 `cause`,是 `command-compact` **既不读 session 也不渲染自己的 error.message**。本插件的 `inject` 里没有 `commands` / `compaction` / `sessions`,也无法重名注册 `compact`(宿主 registry 硬拒)。这是 deepseek-harness 的修复点,不在本仓库能力范围内。
|
|
44
|
+
|
|
5
45
|
## 0.17.0 - 2026-10-09
|
|
6
46
|
|
|
7
47
|
- **[Antigravity] 缓存卡片改为只报「整段未命中」并给出它之前的空闲时长**
|
|
@@ -157,7 +197,6 @@
|
|
|
157
197
|
- 验证:`tsc -b --force` 与 `tsc -p test/tsconfig.json` 通过;`vitest run` 2555 passed / 7 skipped;
|
|
158
198
|
`npm run build` 通过。
|
|
159
199
|
|
|
160
|
-
|
|
161
200
|
- **[MiniMax Code] 支持视频输入;把视频子系统提取为两条线路共享**
|
|
162
201
|
- **视频能力(N6)**:M3 与 M3.1 现在声明并支持视频输入,此前只有文档记载、路由没有实现。
|
|
163
202
|
块形状与 base64 取向**均为实测**,未沿用 Kimi 线的猜测:
|
package/README.md
CHANGED
|
@@ -117,7 +117,7 @@
|
|
|
117
117
|
- 工具调用 id 截断到 64 字符;
|
|
118
118
|
- `stop` 按上限裁剪为最多 5 条、每条 ≤32 字节,超长整条丢弃(截断的停止串会在错误位置终止生成);
|
|
119
119
|
- **K3 的长思考不会被截断**:输出上限跟随上下文窗口(保留 4096 余量),因为 `reasoning_content` 计入输出,固定 32K 会把 `max` 档的长推理中途截断并返回 `length`;调用方已知 prompt 规模时上限会被下调到放得下,未知时不做猜测;
|
|
120
|
-
- **请求体超 2 MB 本地即拒绝**:该端点最常见的 400 是 `total message size N exceeds limit 2097152
|
|
120
|
+
- **请求体超 2 MB 本地即拒绝**:该端点最常见的 400 是 `total message size N exceeds limit 2097152`,官方文案不给建议,这里直接按真实序列化体积拦截,并按「循环实际做了什么」给出处方(有图可丢但丢了也补不上缺口 / 图已丢完仍超限 / 本来无图,三种情况文案不同,不再声称发生了没发生的省略);确有实测上限的部署(前置代理/网关)可设 `DSH_KIMI_CODE_MAX_BODY_BYTES` 指定该档上限,取值非正整数时**回落到默认值而不是关闭守卫**;带视频的请求走 64 MiB 档,不受该变量影响;
|
|
121
121
|
- **缓存是自动的,且无法手动干预**:
|
|
122
122
|
- Kimi 按请求内容哈希命中前缀缓存。实测 `prompt_cache_key` 与 Anthropic `cache_control` 标记**均被忽略**(设与不设、同 key 与异 key 命中的是同一缓存),设备 id 与协议切换也不影响;
|
|
123
123
|
- TTL 实测在 300–1800 秒之间,按 256 token 对齐;`/messages` 与 `/chat/completions` **共享同一缓存**;
|
|
@@ -127,7 +127,8 @@
|
|
|
127
127
|
- 档位在**首次写入时锁定**,之后无法改写、命中时按原档免费续期;1 小时写入约为 5 分钟的两倍价,只有同一前缀会在一小时内被反复读取才划算。不选择时不发任何缓存字段;
|
|
128
128
|
- **视频输入可用**(`k3`、`kimi-for-coding`):
|
|
129
129
|
- DSH 的模态词表只有 `text`/`image`,但它是可合并扩展的接口,本插件用 TypeScript 模块增强把它扩到 `video`(**未改动 DSH 任何代码**),因此视频走 DSH 真实的能力通道,而不是只能显示在提示里;
|
|
130
|
-
- 适配器把视频映射为服务文档的 `{type:'video_url',video_url:{url:'data:…'}}`。视频与图片**各有独立预算**(图片
|
|
130
|
+
- 适配器把视频映射为服务文档的 `{type:'video_url',video_url:{url:'data:…'}}`。视频与图片**各有独立预算**(图片 1.5 MB、视频 48 MiB base64,最旧优先省略),请求体校验只在确实带视频时才放宽到 64 MiB;
|
|
131
|
+
- 图片预算可用 `DSH_KIMI_CODE_MAX_IMAGE_BYTES` 覆盖(取值非正整数时回落到默认值)。视频预算**没有**环境变量出口,与 MiniMax 线路一致;
|
|
131
132
|
- 以下情况会把视频降级为明确的文字说明而不是猜字段发出去:`k3-256k` 只接受图片、文档白名单外的容器、以及未文档化视频内容块的 **Anthropic 线路**;
|
|
132
133
|
- **`dynamically_loaded_tools`(仅 K3)已实现**:K3 接受**消息级工具声明**(`messages[].tools`),可在会话中途用「无 `content` 字段的 system 消息」注入完整工具定义。官方把「保持顶层 `tools` 字节稳定」列为该特性的目的之一——中途修改/删除已发出的声明会使缓存从该点起失效,而在末尾追加不影响已缓存前缀,所以这是提升缓存命中的正道。声明按请求重发(服务端不保留),且仅在模型声明该能力时发送;
|
|
133
134
|
- 额度卡片区分 **5 小时 / 7 天 / 月度(会员共享池)/ 月度(Kimi Code 池)** 四个窗口并显示重置时间,另可显示加油包余额;设置页为「设置 → 订阅服务 → Kimi Code」标签页,对话输入框右侧有该线路的额度胶囊。
|