@eddyskywalker/dsh-chatgpt-subscription 0.29.0 → 0.31.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 +54 -0
- package/README.md +11 -2
- package/lib/client.js +2923 -210
- package/lib/client.js.map +1 -1
- package/lib/index.js +4270 -561
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/minimax-code/MinimaxCodeSection.d.ts +8 -5
- package/lib/types/client/minimax-code/MinimaxCodeSection.d.ts.map +1 -1
- package/lib/types/client/minimax-code/MinimaxVideoDocumentBody.d.ts +69 -0
- package/lib/types/client/minimax-code/MinimaxVideoDocumentBody.d.ts.map +1 -0
- package/lib/types/client/minimax-code/MinimaxVideoToolView.d.ts +83 -0
- package/lib/types/client/minimax-code/MinimaxVideoToolView.d.ts.map +1 -0
- package/lib/types/client/minimax-code/VideoFormDialog.d.ts +90 -0
- package/lib/types/client/minimax-code/VideoFormDialog.d.ts.map +1 -0
- package/lib/types/client/minimax-code/VideoSettingsSections.d.ts +73 -0
- package/lib/types/client/minimax-code/VideoSettingsSections.d.ts.map +1 -0
- package/lib/types/client/minimax-code/commands-contract.d.ts +35 -0
- package/lib/types/client/minimax-code/commands-contract.d.ts.map +1 -0
- package/lib/types/client/minimax-code/document-preview.d.ts +45 -0
- package/lib/types/client/minimax-code/document-preview.d.ts.map +1 -0
- package/lib/types/client/minimax-code/locales.d.ts +212 -8
- package/lib/types/client/minimax-code/locales.d.ts.map +1 -1
- package/lib/types/client/minimax-code/styles.d.ts.map +1 -1
- package/lib/types/client/minimax-code/video-command-host.d.ts +61 -0
- package/lib/types/client/minimax-code/video-command-host.d.ts.map +1 -0
- package/lib/types/client/minimax-code/video-command.d.ts +126 -0
- package/lib/types/client/minimax-code/video-command.d.ts.map +1 -0
- package/lib/types/client/minimax-code/video-contract.d.ts +172 -0
- package/lib/types/client/minimax-code/video-contract.d.ts.map +1 -0
- package/lib/types/client/minimax-code/video-defaults-store.d.ts +61 -0
- package/lib/types/client/minimax-code/video-defaults-store.d.ts.map +1 -0
- package/lib/types/client/minimax-code/video-form-rules.d.ts +288 -0
- package/lib/types/client/minimax-code/video-form-rules.d.ts.map +1 -0
- package/lib/types/client/minimax-code/video-media.d.ts +61 -0
- package/lib/types/client/minimax-code/video-media.d.ts.map +1 -0
- package/lib/types/client/minimax-code/video-slots.d.ts +87 -0
- package/lib/types/client/minimax-code/video-slots.d.ts.map +1 -0
- package/lib/types/host/common/context-overflow.d.ts.map +1 -1
- package/lib/types/host/minimax-code/adapter.d.ts +14 -0
- package/lib/types/host/minimax-code/adapter.d.ts.map +1 -1
- package/lib/types/host/minimax-code/checkin-gateway.d.ts +36 -0
- package/lib/types/host/minimax-code/checkin-gateway.d.ts.map +1 -1
- package/lib/types/host/minimax-code/checkin.d.ts +60 -2
- package/lib/types/host/minimax-code/checkin.d.ts.map +1 -1
- package/lib/types/host/minimax-code/client.d.ts.map +1 -1
- package/lib/types/host/minimax-code/iso-bmff-duration.d.ts +84 -0
- package/lib/types/host/minimax-code/iso-bmff-duration.d.ts.map +1 -0
- package/lib/types/host/minimax-code/mapper.d.ts +51 -19
- package/lib/types/host/minimax-code/mapper.d.ts.map +1 -1
- package/lib/types/host/minimax-code/matrix-client.d.ts +168 -0
- package/lib/types/host/minimax-code/matrix-client.d.ts.map +1 -0
- package/lib/types/host/minimax-code/media-store.d.ts +153 -0
- package/lib/types/host/minimax-code/media-store.d.ts.map +1 -0
- package/lib/types/host/minimax-code/model-catalog.d.ts +40 -15
- package/lib/types/host/minimax-code/model-catalog.d.ts.map +1 -1
- package/lib/types/host/minimax-code/routes.d.ts.map +1 -1
- package/lib/types/host/minimax-code/token-store.d.ts.map +1 -1
- package/lib/types/host/minimax-code/types.d.ts.map +1 -1
- package/lib/types/host/minimax-code/video-history.d.ts +240 -0
- package/lib/types/host/minimax-code/video-history.d.ts.map +1 -0
- package/lib/types/host/minimax-code/video-submit-rules.d.ts +40 -0
- package/lib/types/host/minimax-code/video-submit-rules.d.ts.map +1 -0
- package/lib/types/host/minimax-code/video-tool.d.ts +757 -0
- package/lib/types/host/minimax-code/video-tool.d.ts.map +1 -0
- package/lib/types/host/progress-updates/index.d.ts +6 -0
- package/lib/types/host/progress-updates/index.d.ts.map +1 -1
- package/lib/types/host/progress-updates/projection.d.ts +214 -0
- package/lib/types/host/progress-updates/projection.d.ts.map +1 -0
- package/lib/types/host/proxy-manager.d.ts.map +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/shared/minimax-code-contracts.d.ts +17 -3
- package/lib/types/shared/minimax-code-contracts.d.ts.map +1 -1
- package/package.json +13 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,60 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.31.0 - 2026-10-20
|
|
6
|
+
- **[minimax-code] 视频生成现在能带素材、选比例:首/尾帧、参考图/视频/音频、任意比例与 AIGC 水印**
|
|
7
|
+
- **为什么能带素材**:上游那套媒体工具走的**不是**平台 API Key,而是**订阅网关** —— 和我们 Messages 线路同一个 origin、同一把订阅令牌、四个请求头。所以生成视频不需要额外配 Key。
|
|
8
|
+
- **最容易错的地方**:**参数名 ≠ 发给服务端的字段名**。`inputImagePath` 上线是 `input_image`、`referenceImagePaths` 是 `reference_images` —— 照参数名直接发,全部会失败。映射在媒体准备层里写明。
|
|
9
|
+
- **比例是联动的,不是照抄**:给了首/尾帧 → 服务端**强制** `adaptive`(用户给的值会被改写);有参考媒体 → 缺省 `adaptive`;纯文本 → 缺省 `16:9`,且**`adaptive` 会被本地拒绝**(纯文本没有可自适应的对象,发出去只是白花一次计费的请求)。
|
|
10
|
+
- **两处刻意偏离上游**:① H3 家族缺省分辨率是 `2K`——但**只在 `2K` 属于该模型合法集时才下发**(H3-Max 实测只收 `480P`/`768P`,照抄会让每个省略分辨率的 H3-Max 调用都变成「必然被拒的计费提交」);② 参考视频的时长**本地文件自己从容器读**(`mvhd` box),**不引入 ffmpeg 依赖**、也不要求用户填——只有公网 URL 才需要,因为服务端不下载它、算不出长度。
|
|
11
|
+
- **重复提交会被拒**:生成是**计费的**,而模型可能在一轮里调两次同一个工具。同一会话同一轮里的**同一份 body** 只发一次(请求**发出前**就记下,所以失败的那次也不会被重发成第二次扣费)。**但没有会话标识时这个防护不启用**——键会退化成「只有 body」,两个不同的生成会被误判成重复,**误杀比漏杀更糟**。
|
|
12
|
+
- **文件上传**:本地素材走我们**已经实测跑通**的那条通道(预签名 PUT → `cdn_url`),并带上上游实测的 `category`。第三方公网 URL **本地就拒绝**——实测两个能取到正确 MP4 字节的独立主机,服务端一律拒绝(原话 `video_info.url could not be used as a media source`)。
|
|
13
|
+
- **验证**:全部用 mock 单测(本轮**没有跑真实生成**)。上游契约逐行比对自 `MiniMax-AI/minimax-code` 的 `tool-defs.ts` / `submit-video-generation.ts` / `file-transfer.ts`。
|
|
14
|
+
- **[minimax-code] 视频工具终于有了用户能碰到的入口:`/video` 命令 + 设置页的默认参数与生成历史**
|
|
15
|
+
- **之前只能用自然语言触发**,模型自己决定调不调;而参数并不显然(比例会被改写、每个模型的时长与分辨率合法集不同)。
|
|
16
|
+
- **`/video`**:斜杠菜单里列出**实测合法**的预设档,再加一行「自定义…」打开完整表单(提示词/模型/比例/时长/分辨率/首帧/末帧/参考图/参考视频与时长/参考音频/水印)。**只填进输入框、不直接发送** —— 用户得先看见联动把它的参数改成了什么。
|
|
17
|
+
- **只在 minimax-code 线路上出现**:斜杠菜单的可见性判据读会话的 `modelSelection` 投影(宿主自己就是这么读当前模型的),别的线路上**菜单里根本没有这一行**;工具本身还有一道 provider 门禁。
|
|
18
|
+
- **参数联动在表单层就处理完**:给了首帧 → 比例选择器**消失**,只显示强制值和理由;纯文本 → `adaptive` 根本不在选项里;换了模型 → 时长与分辨率收窄到该模型的实测合法集。
|
|
19
|
+
- **设置页**新增两格:**默认参数**(存浏览器,纯 UI 起手值)与**生成历史**(存宿主,因为写它的是工具执行;沿用仓库惯例走平台加密后端,**只存路径与数字、不存视频内容**)。
|
|
20
|
+
- **两处「源码里有、产品里没有」的修复**:`remote.workspaceFiles` 是独立服务名不是 `remote` 的属性(照属性读会被 Cordis 的属性守卫抛错 → 每次读视频都失败);`documentPreviews` 由宿主 `reflect.provide` 且**晚于本插件激活**(照 `apply` 瞬间抓一次 → 侧边栏预览视频从来不会生效)。
|
|
21
|
+
- **[进展更新] 面板记录改为从会话日志投影折叠:重开对话、刷新页面、宿主重启之后历史还在**
|
|
22
|
+
- **现象**:右侧栏「进展更新」面板的记录**完全没有持久化** —— 进展只活在一个进程内的环形缓冲里([`store.ts`](../src/host/progress-updates/store.ts) 的 `MAX_UPDATES = 50`),[`index.ts`](../src/host/progress-updates/index.ts) 按会话分桶存进一个 `Map`,卸载时 `stores.clear()`。重开对话、刷新页面、宿主重启,面板就空了。
|
|
23
|
+
- **数据其实一直在**:`progress_update` 的每次调用都是一条会话事件,早已被 DSH 持久化。注意它有**两种形状**:原生调用落 `tool/call`(`arguments` 是模型吐出的 JSON 原文),而 PTC 模式(模型只看得见 `run_code`,把 `progress_update` 当子调用发出去)落 `tool/ptc-dispatch`(`arguments` 是**已解析的对象**,且那一条 `tool/call` 的 `name` 是 `run_code`)。丢的只是"从日志里把它读回来"这一步。
|
|
24
|
+
- **改法(新增 [`projection.ts`](../src/host/progress-updates/projection.ts))**:登记一个会话投影单元,把日志里的 `progress_update` 折叠成一条条进展,**日志成为唯一真源**。`apply` 认**两种**形状(`tool/call` + `tool/ptc-dispatch`,都要求 `name === 'progress_update'`),各按自己的参数形状取 `{ title, message }`,`at` 取事件时刻;其余任何情况(两种都不是、不是这个工具、参数不是合法 JSON / 不是对象、`message` 不是字符串、缺 `seq`/`time`)**一律返回同一个 state 引用且绝不抛错** —— 这是日志重放路径,抛一次就毁掉整条折叠链。
|
|
25
|
+
- **折叠语义变了就 +1**:`stateVersion` 因此是 **2**。缓存按 `(sessionId, key, ver, seq, val)` 落盘,而上一版按"只认 `tool/call`"的语义已经写进了一份 `{ver:1, seq:…, val:{updates:[]}}` 的空数组;版本不升的话它会被当成有效 checkpoint 续用,面板会一直空着。
|
|
26
|
+
- **id 用 seq,还带上会话 id**:`pu-<seq>-<sessionId>`。时间戳会随重放时的时钟漂移,seq 不会,同一段日志重放两次得到逐字相同的 id(客户端 `sameList` 按 id 比较,面板也拿 id 当 React key)。后缀解决另一半问题 —— 读值要合并整棵委派树,而 seq 在每个会话里都从 0 开始,只带 seq 会让根会话与子会话的第一条进展撞 id。
|
|
27
|
+
- **改法([`index.ts`](../src/host/progress-updates/index.ts) 的 `updatesOf`)**:**先投影、后内存**。投影路径用 `sessions.get(id)` 拿到会话对象,再用 `sessionProjections.stateOf(session, 'progressUpdates')`(没有就退 `snapshot` 的 wire 切面)读值;**整棵委派树共用一份进展**的语义照旧保留 —— 沿 `header.parentSession` 把 `sessions.list()` 里活跃的子孙找回来(深度上限 16,与 `nudge.ts` 的 lineage 走法同一个数),按 `at` 升序合并后仍按 `MAX_UPDATES` 截断。会话/投影服务缺席、会话还没 attach、投影登记被拒 —— 都**安静回退**到内存 `Map`,行为与今天完全一致。
|
|
28
|
+
- **内存 `Map` 没有删**:它同时承担催促计数(`roundsSinceUpdate`/`nudges`)与降级路径;HTTP 路由、催促逻辑、工具注册、提示词分节一个字没动,客户端取数通道也仍是原来的 2 秒轮询。
|
|
29
|
+
- **兼容性**:`@deepseek-ai/dsh-session-projection` **不在** peerDependencies 里,运行时**不 import** 它 —— 投影定义按结构化类型自己声明(同 `nudge.ts` 的 `NudgeSessionLookup` / `TurnBoundaryLookup`),服务只经 `ctx.get('sessionProjections')` 读取,缺席就降级。`zod` 因此进 `dependencies`(`4.4.3`,与 DSH 侧一致):它在 `lib/index.js` 里保持为一条裸的 `import { z } from "zod"`,由包的 `dependencies` 在安装时解析(tsdown 默认把 `dependencies` 里的包外部化,不会被内联进 bundle)。`package-lock.json` 同步声明了这条依赖(CI 跑的是 `npm ci`)—— 只动了这两行,没有整份重生成:那份锁文件本来就停在 0.26.1 且带着两条早已不在 `package.json` 里的 devDependencies,顺手重写会把它一并对齐,超出这次改动的范围。
|
|
30
|
+
- **验证**:`npm run typecheck` 0 错误;`npm test` **4079 passed / 7 skipped**;`npm run build` 通过。除单测外还拿**真实会话日志**重放过一遍:解压 `session.v4.jsonl.zstd`(509 个 zstd 帧)后确认 `tool/call` 全是 `run_code`、`progress_update` 全在 `tool/ptc-dispatch` 里,按新 `apply` 重放折出 10 条,与对话流里看到的进展行一一对上。新增两份测试 30 例:[`test/progress-updates-projection.test.ts`](../test/progress-updates-projection.test.ts)(折叠字段、无关事件返回同一引用、坏 JSON / 缺字段不抛错、`MAX_UPDATES` 截断、重放 id 稳定、schema 与合并)与 [`test/progress-updates-projection-source.test.ts`](../test/progress-updates-projection-source.test.ts)(投影优先、委派树合并、无投影服务时照常挂载并走内存、会话未 attach 时回退、登记被拒时降级)。
|
|
31
|
+
|
|
32
|
+
## 0.30.0 - 2026-10-20
|
|
33
|
+
- **[minimax-code] 请求的模型与实际回答的模型不一致时,这一轮立刻失败——而不是替用户按最贵档付费**
|
|
34
|
+
- **现象**:这条路由**不拒绝**它路由不了的模型 id。2026-10-20 实测:乱写串与空串都回 HTTP 200,实际由 `MiniMax-M3` 代答;同一个乱写 id 带 `reasoningEffort:'none'` 重发,回答的 M3 真的少了 thinking 块——是**真替换**,不是把名字写回去的壳。
|
|
35
|
+
- **为什么要紧**:我们的模型目录是硬编码的(`/v1/models` 对订阅流量是 503 `direct_route_not_configured`,那是路由裁决不是路径拼错)。若 MiniMax 下架了 M2.7 而用户仍选着它,请求**不会报错**,会被 M3 代跑——用户以为在用便宜模型,实际按最贵档计费(我们自己的实测:M3 的 max 档思考量约 3 倍、延迟约 4 倍)。**这是钱包问题,不是可用性问题**,而且**没有错误报文可依**。
|
|
36
|
+
- **改法**:[mapper.ts](../src/host/minimax-code/mapper.ts) 读流头的 `message_start.message.model`(此前只取 usage 与 stop_reason);[adapter.ts](../src/host/minimax-code/adapter.ts) 把它与**真正上线的那串 id** 比对(从即将发送的请求体读回,不是目录解析名),不一致则抛 `MODEL_SUBSTITUTED`。
|
|
37
|
+
- **判定点与代价**:判定在 `processMinimaxStreamLine` 之后、**任何 `yield` 之前**——`message_start` 是流的第一个事件,排在所有 `content_block_start` 之前,所以**没有任何内容块送达调用方**,无需回收、不会有重试重复输出。新码**不在** `retryableCodes` 里:重发同一 body 只会再被替换一次,并按替身计费。
|
|
38
|
+
- **验证**:`npm run typecheck` 0 错误;全量 **250 passed | 1 skipped(251 文件)、4050 passed | 7 skipped、0 failed**;`npm run build` 通过。新增 5 条守卫(一致 / 不一致且零内容块 / 无 model 字段 / 大小写双向 / mapper 层单测)。
|
|
39
|
+
- **[minimax-code] 每日签到锁定在它开始的那一个账号上:池行被重绑就重新认,attempt 中途换号就拒绝**
|
|
40
|
+
- **现象**:签到读面板用 A 的 `realUserID`、领取用 B 的凭据是可能的——网关把 `accessToken` 与 `realUserID` 当两个独立入参,彼此没有绑定校验,而 `realUserID` 是按池行缓存的。
|
|
41
|
+
- **两个真实窗口**:① 状态文件钉着 A、池里那一行已被换成 B;② 401 强制续期后 `renewCredential` 返回**另一个账号**的凭据,重试即以别人的账号领取。
|
|
42
|
+
- **两者性质不同,处理也不同**:① **重绑是合法的状态变化**——一行 = 插件替用户管理的一个账号,跟着走才是对的,所以**用当前凭据重新解析身份、重新钉住、照常签到**(老状态文件也会在第一次运行时自愈);② **attempt 中途的漂移与 401 续期换号必须硬拒绝**(`MinimaxCodeCheckinAccountMismatchError`),不自愈。
|
|
43
|
+
- **记一个容易骗人的地方**:`native:<region>:<recordKey>` 里的 `recordKey` 是**记录槽位**键,**不是账号 id**——用户在桌面端把另一个账号签进同一槽位时它不变。所以它只是「尽力而为的护栏」,这条线账号的**权威标识**是从身份接口解析出来的 `realUserID`。
|
|
44
|
+
- **验证**:签到相关 5 套件 **113 passed**;两次**变异验证**(关掉钉校验 → 两条用例红;关掉漂移守卫 → 漂移用例红),均已还原。
|
|
45
|
+
- **[minimax-code] 额度耗尽改按上游数字码判定,措辞表留作兜底;并纠正我们文档里的过度声称**
|
|
46
|
+
- **改法**:[adapter.ts](../src/host/minimax-code/adapter.ts) 的 `statusCodeIn` 读三处信封(`base_resp.status_code` → `errorCode` → **顶层 `code`**),命中上游的 `2056`/`2067` 即判账号级额度耗尽;403 与 429 两个入口读**同一个**谓词、汇进**同一个**判决,形状天然一致。**2013 明确排除**(通用「参数非法」码,本仓库在 reset-card 与 Files API 上另有语义)。
|
|
47
|
+
- **实测订正**:Messages 路由的错误信封**没有 `base_resp`**——400 是 `{type,error{type,message}}`(无任何数字字段),401 是 `{code,message}`。所以这条路由上**当前真正 operative 的仍是措辞表**,数字码臂是**跨信封的前向兼容臂**。README 里那段把它写成首要判据的话已改正。
|
|
48
|
+
- **验证**:新增 8 条(数字码 / 措辞 / 两者同形 / 2013 不判 / 顶层 401 不判 / 流内继承),邻近 6 套件 133 passed。
|
|
49
|
+
- **[minimax-code] 令牌时长从「约 24 小时」纠正为「约 1 小时」,设置卡改用分钟显示**
|
|
50
|
+
- **现象**:卡片上写着访问令牌约 24 小时有效,而实测是**一小时**(`types.ts`)——一句用户会读到的错话;余量又以「小时」报,一小时寿命的令牌因此看不出 Host 何时会续期。
|
|
51
|
+
- **改法**:`remainingHours` → `remainingMinutes`,单位改分钟(恒定一位小数,不足一分钟视为已过期),中英文案同步改为「约 1 小时」。
|
|
52
|
+
- **[minimax-code] 能力说明与上游差分归档:七处过期表述 + 活体探针 + 差分文档**
|
|
53
|
+
- **代码早于文档**:Files API 早就实现了(上传 / 12 小时 TTL / 账号隔离 / 去重缓存),视频也早已声明,而 `model-catalog.ts` 的三处注释与 README 仍在描述实现之前的世界——这会让人误判这条线路的能力边界,包括下一次做差分分析的人。
|
|
54
|
+
- **新产物**:`scripts/probe-minimax-capabilities.probe.ts`(16 个 case 的活体探针)与 `docs/minimax-code-probe-capabilities.md`(原始证据),以及 `docs/minimax-code-upstream-delta-v2.md`(本轮上游差分、明确否掉的项、待办)。
|
|
55
|
+
- **顺带量出**:服务侧 `max_tokens` 真阈值是 **524288**(128000 / 512000 都接受,999999999 回 400)——我们写的 128000 是保守值(与上游兜底表一致),**数值未改**;并确认那条 400 文案**不会**误触发上下文超限检测,不存在「压缩→重试→再压缩」的死循环。
|
|
56
|
+
- **[Codex 搜索] 读出活体搜索真正的答案字段,并给代理一个连接超时**
|
|
57
|
+
- **现象**:活体 `/alpha/search` 的回答在顶层 `output` 字段,而 `readContent` 只看 `content` / `output_text` / `summary`——于是每次真实搜索都**没有答案正文**,工具只报一串来源,读起来像「搜索能用,只是没搜到东西」。
|
|
58
|
+
- **代理**:undici 默认 10s 连接超时覆盖的是到**源站**的 TLS 握手而非到代理的那一跳;实测某条到 chatgpt.com 的慢路由仅握手就 1.2s–18s、请求整体 31s,默认值把本该几秒后成功的请求杀掉,而且是以一句不点名的 `fetch failed` 杀掉。代理 agent 改为 60s 连接超时,并用 undici 真正接受的 options 对象形式传入(第二个位置参数会被静默丢弃)。
|
|
5
59
|
## 0.29.0 - 2026-10-19
|
|
6
60
|
- **[Antigravity] 429 不再被当成「配额耗尽」:裸 429 不冷却账号、不换账号,也不再把上游原因藏起来**
|
|
7
61
|
- **现象**:账号配额还很充足(实测 Gemini 5h 桶剩余 95.95%、周桶剩余 84.67%,Claude/GPT 100%),插件却报「账号配额已耗尽」,并把该账号的 Gemini 配额族冷却 15 分钟;此后每次重试都被账号池直接挡下,连一次网络请求都不发。
|
package/README.md
CHANGED
|
@@ -191,8 +191,17 @@
|
|
|
191
191
|
- 该端点的 `GET /v1/models` **未对订阅流量开放**(503 `"{\"errorCode\":50115,\"errorReason\":\"direct_route_not_configured\"}"`),所以任何「实时目录」都只会是一个必然失败的请求;
|
|
192
192
|
- 四款模型:M2.7 / M2.7 HighSpeed / M3 取自本机 `~/.minimax/config.yaml` 的模型表;**M3.1 Flash 是 2026-10-19 换上的正式版 id**(`MiniMax-M3.1-Flash`,去掉了 `-Preview` 后缀),取自 MiniMax 自己的 Model Invocation 页 Supported Models 表并在该订阅端点上实测(正式 id、`output_config.effort` 的 low/max、内联图片)。无论哪一条,**都不从不存在的接口推断**;
|
|
193
193
|
- **思考形态按模型表三态实现,且一律走 `output_config`,不发 `thinking` 对象**(该字段从未被文档确认,发出去只是一种形状的猜测):M2.7 系列**恒定开启且没有档位**(不发送任何字段);M3 是**开关二态**(关闭时 `output_config.effort: 'none'`);M3.1 Flash **强制开启并可指定档位**(`output_config.effort` 取 low/medium/high/xhigh/max,省略即 max)。未知或越档的取值一律回落到该模型目录声明的默认档,不会把模型没有声明的档位发出去;
|
|
194
|
-
-
|
|
195
|
-
-
|
|
194
|
+
- **视频已在能力声明里,并且真的能发出去**:M3 与 M3.1 Flash 的 `inputModalities` 都是 `['text', 'image', 'video']`(`model-catalog.ts`),线上形状取自实测——`{ type: 'video', source: { type: 'base64', … } }` 被该端点接受并解码(同一段实测也否掉了 data-URL 字符串那种封装,它会在 `:` 处按裸 base64 解码失败)。**能不能读到字节是宿主注入的接缝**:`AttachmentVideoReader`(`adapter.ts:372`,类型在 `src/host/common/video-request.ts`)由宿主提供,DSH 自己的附件服务只存图片,所以视频只能来自本部署里某个真实的生产者;宿主不提供读取器、或某一条读不出来时,`resolveRequestVideos` 把它解析成 `unavailable`,映射器(`mapper.ts:416`)才退化成一段说明文本——`modalities.ts` 的 `videoOmissionText` 按 4 种 reason 给出各自不同的措辞(`unsupported-model` / `unsupported-container` / `unreadable` / `unsupported-wire`),让模型知道「有这段视频、为什么没带上」,而不是对着空白回答。**降级发生在单个片段上,不发生在声明上**:声明的依据是接缝存在且线上形状实测可用,不是「任何情况下都一定能读到」;
|
|
195
|
+
- **失败按 8 级判决分类,判词决定重试与号池动作**(`classifyMinimaxFailure`,`adapter.ts:388-470`;读的是**原始正文**而不是 `summarizeFailureBody` 抽出的那一个字段,因为同一个判词在两种信封里放的位置不同):
|
|
196
|
+
- **上下文超限**——`isHttpContextOverflow` 先判,`CONTEXT_OVERFLOW_CODE`,终局、不归账号;
|
|
197
|
+
- **账号级额度耗尽**——**`403` 或 `429`** 都可能落到这一类,判据是正文**点名了一个用尽的窗口**,与状态码无关:`isSpentWindow403`(`adapter.ts:355`)管 403,`429` 分支(`adapter.ts:425-431`)用同一个谓词问同一个问题,两条都返回**同一个** `quotaExhaustedFailure`(`adapter.ts:368`:`PROVIDER_ERROR` / `retryable: false` / `accountScoped: true`)。**判据本身是两个臂**(先问上游用量限额的**数字码**、再问**措辞表**兜底;这个先后只是求值顺序,不代表这条路由上真正会开火的是前者):`namesUsageLimitStatusCode`(`adapter.ts:311`)读两种信封里的上游码(平台信封 `base_resp.status_code`、客户端信封 `errorCode`,并额外往流内错误体 `{ error: … }` 里多读一层),命中 `USAGE_LIMIT_UPSTREAM_STATUS_CODES = {2056, 2067}` 即算;非 JSON 或没有该字段的正文回落到措辞表 `QUOTA_EXHAUSTED_PATTERNS`。两个臂汇进同一个判决 `namesSpentWindow = namesUsageLimitStatusCode || 措辞表`(`adapter.ts:334`)——它们不是两套规则,而是同一个问题的两种承载方式:一句中文没有码,一个裸码没有句子。**但要把定位说准**:数字码臂在这条 Messages 路由上目前**不会开火**,它是**跨信封的前向兼容臂**(哪天服务真的在 Messages 路由上带出 `2056`/`2067`/`errorCode`,它就会生效),**不是这条路由当前的主要判据**。2026-10-20 的活体探针(`scripts/probe-minimax-capabilities.probe.ts`,原始证据 `docs/minimax-code-probe-capabilities.md`)把这条路由的错误信封量了个遍:端点上只有**两种**信封,**没有一种带 `base_resp`**——① 请求被拒 `400` 是 `{"type":"error","error":{"type":"invalid_request_error","message":"…"}}`(参数类错误上多一个 `request_id`),**没有任何数字字段**;② 认证被拒 `401` 是 `{"code":401,"message":"auth failed"}`,**顶层 `code` 是这条路由唯一的数字字段**。`base_resp.status_code` 那个信封属于这条线路的**别的**路由(配额 `coding_plan/remains`、Files API、`reset-card`),不属于 Messages。连探针抓到的 `2013` 也**不是字段**:它只以文本形式嵌在 `error.message` 的括号里(`… does not support max tokens > 524288 (2013)`),而且是**通用「参数非法」码**——超限的 `max_tokens`、空 body、畸形 JSON 全都归它;本仓库在 `reset-card` 与 Files API 上另有语义,**绝不拿它当额度判决**。所以在 Messages 路由上**当前真正 operative 的那一条是措辞表**:数字码臂留在这里,是为了不让一个将来可能带上数字码的信封被当成措辞去猜,而不是因为这条路由现在会给码。它必须排在下面的凭据分支**之前**,因为 `401`/`403` 的正文在这条线上是同一句 `token is required`,光看状态码分不出「窗口用尽」与「凭据被拒」。号池据此冷却到窗口重置(未命中周窗口词冷却 5 小时,命中 `WEEKLY_QUOTA_WINDOW_PATTERN` 冷却 7 天,见 `adapter.ts:172-184`),且**刻意不采信 Retry-After**——等 N 秒不会让一个用尽的窗口重新可用;
|
|
198
|
+
- **凭据失效**——`401`/`403` 里不属于上面的,`INVALID_CREDENTIAL`,终局且归账号,但走 `markAuthFailed` 而不是 `markCooldown`;这条线的 401 正文在「没发凭据」和「凭据被拒」两种情况下是同一句 `token is required`,所以提示直接指向重新登录;
|
|
199
|
+
- **纯背压 429**——**没有**点名用尽窗口的 429(数字码与措辞两个臂都没命中),`RATE_LIMIT`,**可重试**且**不归账号**(同一套餐后面的每个账号都会被同样拒绝,冷却它只会把号池抽干);
|
|
200
|
+
- **5xx**——`SERVER`,可重试、不归账号;
|
|
201
|
+
- **400**——`PROVIDER_ERROR`,终局:请求本身不被接受,重发一次也不会被接受;
|
|
202
|
+
- **其他状态码**——`PROVIDER_ERROR`,终局,正文为空时提示「无响应」;
|
|
203
|
+
- **401 另有一次性补救**(合并下方一条):第一次 401 会**强制续期一次并原样重试同一个请求体**,重试再被拒才是终局;
|
|
204
|
+
- 可重试的四类(`RATE_LIMIT` / `SERVER` / `TIMEOUT` / `TRANSPORT`)走 DSH retry policy 的有界退避:最多 3 次,1.5s 起步、15s 上限、0.2 抖动;**终局类不重试**——重试只会推迟用户真正需要看到的那句提示;
|
|
196
205
|
- **401 会强制续期一次再重试**:本地时钟看着还有效、服务端却拒收的令牌(在桌面端被撤销、时钟偏移、桌面端已轮换)与「真的需要重新登录」在状态码上无法区分,所以第一次 401 会**强制刷新一次并原样重试同一个请求体**;重试再被拒才是终局;
|
|
197
206
|
- **刷新令牌是单次使用的,因此续期提前 5 分钟、并全进程共用一次轮换**:
|
|
198
207
|
- 这是「每小时自己掉线、然后要求重新登录」的根因。access token 实测只有 **1 小时**,而原先的续期阈值是「到期前 60 秒」——等于每次都在令牌已经会被拒收的那一瞬间才去轮换;
|