@eddyskywalker/dsh-chatgpt-subscription 0.27.1 → 0.28.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 +23 -0
- package/README.md +2 -2
- package/lib/client.js +119 -6
- package/lib/client.js.map +1 -1
- package/lib/index.js +64 -18
- package/lib/types/client/progress-updates/markdown-lite.d.ts +30 -4
- package/lib/types/client/progress-updates/markdown-lite.d.ts.map +1 -1
- package/lib/types/client/progress-updates/progress-row.d.ts.map +1 -1
- package/lib/types/host/minimax-code/model-catalog.d.ts +32 -4
- package/lib/types/host/minimax-code/model-catalog.d.ts.map +1 -1
- package/lib/types/host/minimax-code/types.d.ts +1 -1
- package/lib/types/host/subagent-model-authorization.d.ts +3 -3
- package/lib/types/index.d.ts +1 -1
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.28.0 - 2026-10-19
|
|
6
|
+
- **[MiniMax Code] 模型目录跟上正式版:`MiniMax-M3.1-Flash` 取代 `MiniMax-M3.1-Flash-Preview`,并给存量用户留了一条迁移路**
|
|
7
|
+
- **上游改名了**:MiniMax 于 2026-10-19 发布正式版 `MiniMax-M3.1-Flash`(官方 Model Invocation 页的 Supported Models 表已不再带 `-Preview` 后缀,1,000,000 上下文)。我们随包的硬编码目录里那条 `MiniMax-M3.1-Flash-Preview` 已经不是上游当前的名字。
|
|
8
|
+
- **先实测,再改目录**:用本机设备码凭据打国区订阅端点 `https://agent.minimax.cn/mavis/api/v1/llm/v1/messages`,三个 id 各发一次真实请求,全部 **HTTP 200** 且服务回显同名——`MiniMax-M3.1-Flash`(新)、`MiniMax-M3.1-Flash-Preview`(旧,仍未被下线)、`MiniMax-M3`(对照)。正式版另测两项能力:`output_config.effort` 真生效(同一 prompt 下 `low` 289 思考 token / `max` 412),内联图片块被接受并正常作答(多模态可用)。
|
|
9
|
+
- **改法一(目录换名)**:[model-catalog.ts](../src/host/minimax-code/model-catalog.ts) 第四条改为 `MiniMax-M3.1-Flash`(显示名 `MiniMax M3.1 Flash`)。**1M 上下文取自官方 Model Invocation 页**,思考强制开启 / effort 可调 / 收图三项为 2026-10-19 实测;**输出上限 128k 与 4 附件这两个数是沿用 Preview 条目的**(官方只公布上下文,不公布输出上限与每模型附件数),注释里写明未重测。
|
|
10
|
+
- **改法二(存量勾选不再被丢掉 —— 本轮真正的坑)**:`resolveMinimaxCodeEnabledModelIds` 会把目录里没有的 id 全部过滤掉。别的用户 `enabledModelIds` 里存着 `MiniMax-M3.1-Flash-Preview`,换名后这一条被丢掉;**如果他只勾了这一个模型,升级后模型选择器会一个都不剩**。因此目录加了一张**单向改名映射**(旧 id → 新 id),并让它在四个地方生效:查目录条目、`isMinimaxCodeModelId`、存量勾选解析(去重后不重复列)、以及**按旧 id 存过的上下文窗口覆盖**继续生效。默认勾选「未编辑过」的判定也改在解析之后做,所以用旧拼写写下的完整默认列表仍按「随目录增长」处理。
|
|
11
|
+
- **改法三(线上的 id 不动)**:改名只发生在**查找**层,**发上线路的 model 字段仍按调用方给的那个 id 走**。已有会话记录里的 id 因此原样保留,它带着的 thinking 签名回放作用域(route/model/authOwner)不会因为换名而失配——把 wire 也改掉会让在途会话的回放校验对不上。
|
|
12
|
+
- **文档同步**:README 里「四款模型」与「思考形态三态」两条(后者原本还在写早已不用的 `thinking` 对象,已改为 `output_config`)、视频占位提示文案、`types.ts` 的过期注释、[subagent-model-authorization.ts](../src/host/subagent-model-authorization.ts) 的示例路由串、5 个测试文件里的模型 id 全部改为正式版;[docs/minimax-code-gap-plan.md](docs/minimax-code-gap-plan.md) 补记改名事实并说明其中引用的官方原文保持不动。
|
|
13
|
+
- **验证**:`npm run typecheck` 0 错误;全量 **247 passed | 1 skipped(248 文件)、3997 passed | 7 skipped、0 failed**(新增 `test/minimax-code-model-rename.test.ts` 9 例,钉住「目录只列新 id」「旧 id 仍解析到同一条目」「存量勾选不丢」「两种拼写不重复列」「旧 id 的窗口覆盖继续生效」「卡片按新 id 显示为已勾选」)。
|
|
14
|
+
|
|
15
|
+
## 0.27.2 - 2026-10-18
|
|
16
|
+
- **[进展更新] 正文补上 GFM 表格,对话流与侧栏面板改用同一个渲染器**
|
|
17
|
+
- **现象**:模型在进展正文里写 GFM 表格(`| 题 | 难度 |` + `| --- | --- |`)时,面板把整块表格**原样**显示成一堆竖线;同时对话流里的主形态(`progress-row.tsx`)正文是纯文本 `<p>{message}</p>`,连 `**粗体**` 都不解析——同一份进展在侧栏渲染过、在对话流里是原文,两处观感对不上。
|
|
18
|
+
- **改法一(`markdown-lite.tsx`)**:补 GFM 表格块。识别用**两行前瞻**(本行含 `|` 且下一行是分隔行 `| :--- | ---: |`):孤立的竖线不会被误判成表格;支持 `:---` / `:---:` / `---:` 三种对齐、单元格内 `\|` 转义、数据行短于表头时补空格子。渲染成真实 `<table>/<thead>/<tbody>/<th>/<td>`,对齐落在 `text-align` 上,窄屏外包一层 `overflow-x:auto`。仍然**零依赖**、不经 `dangerouslySetInnerHTML`。
|
|
19
|
+
- **改法二(`progress-row.tsx`)**:正文改用同一个 `MarkdownLite`,并去掉外层 `white-space: pre-wrap`(换行该由块级元素决定,而不是靠保留原文换行)。两处观感自此一致。
|
|
20
|
+
- **改法三(提示词与工具描述)**:`prompt.ts` 的正文写法与 `tool.ts` 的 `message` 参数描述都补了一句「有几行数据要对照时用 GFM 管道符表格」,让模型知道表格现在真的会被渲染出来。
|
|
21
|
+
- **仍然不做**:图片、链接、原始 HTML、脚注、围栏代码块——要么需要安全过滤,要么不属于「进展汇报」这个场景。
|
|
22
|
+
- **验证**:`npm run typecheck` 0 错误;全量 **246 passed | 1 skipped(247 文件)、3988 passed | 7 skipped、0 failed**;`npm run build` 通过,`lib/client.js` 里已含 `md-table`/`md-th`/`md-td` 标记。新增 3 条回归(面板表格 / 孤立竖线不误判 / 对话流也渲染),并做变异验证:把表格识别分支关掉,其中两条立刻变红(2 failed),恢复后 31 passed。
|
|
23
|
+
|
|
24
|
+
## 0.27.1 - 2026-10-18
|
|
25
|
+
- **仅版本号变更**:`package.json` 由 0.27.0 提到 0.27.1,源码零改动(`git diff v0.27.0 v0.27.1` 只有一行版本号)。
|
|
26
|
+
- **补记原因**:0.27.1 当天已发布到 npm(2026-10-18T04:31:48Z),但发版时漏打了 git tag、也没在 CHANGELOG 留记录,导致版本线在 git 侧断了一格。事后**只在本机补了 `v0.27.1` 标签**(指向 `f75bc78`),**未推送**——推上去会让 CI 去发布一个已存在的版本而失败。
|
|
27
|
+
|
|
5
28
|
## 0.27.0 - 2026-10-18
|
|
6
29
|
- **【进展更新】agent 在多步任务中主动汇报,对话流里一行一条,右侧栏可回看**
|
|
7
30
|
- **是什么**:新增 in-tree 子模块 `src/host/progress-updates/` + `src/client/progress-updates/`,复刻 Kimi Code 的「进展更新」。agent 通过一个**不结束回合**的工具 `progress_update(title?, message)` 主动汇报,对话流里渲染成一行(状态点 + 标题 + 状态词,正文点开看),右侧栏有一个总览面板。
|
package/README.md
CHANGED
|
@@ -189,8 +189,8 @@
|
|
|
189
189
|
- **区域是凭据属性**:`cn` 用 `account.minimax.cn` / `agent.minimax.cn`,`global` 用对应 `.io` 域名。两个区域的目录都会被探测,因此国际区账号不会因为没有国区文件而「未登录」;读回凭据时**以记录里存的区域为准**,而不是拿默认区域覆盖它;
|
|
190
190
|
- **模型目录是硬编码的,而且必须硬编码**(`src/host/minimax-code/model-catalog.ts`):
|
|
191
191
|
- 该端点的 `GET /v1/models` **未对订阅流量开放**(503 `"{\"errorCode\":50115,\"errorReason\":\"direct_route_not_configured\"}"`),所以任何「实时目录」都只会是一个必然失败的请求;
|
|
192
|
-
-
|
|
193
|
-
-
|
|
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
|
+
- **思考形态按模型表三态实现,且一律走 `output_config`,不发 `thinking` 对象**(该字段从未被文档确认,发出去只是一种形状的猜测):M2.7 系列**恒定开启且没有档位**(不发送任何字段);M3 是**开关二态**(关闭时 `output_config.effort: 'none'`);M3.1 Flash **强制开启并可指定档位**(`output_config.effort` 取 low/medium/high/xhigh/max,省略即 max)。未知或越档的取值一律回落到该模型目录声明的默认档,不会把模型没有声明的档位发出去;
|
|
194
194
|
- **视频不在能力声明里**:模型表虽然给 M3 / M3.1 标了视频输入,但 DSH 的附件服务只存图片、本线路也没有安装视频字节读取器,映射器只能把它替换成一条说明文本。**声明一个做不到的能力比不声明更糟**(DSH 的能力闸门、模型选择器与子代理委派都会当它成立),所以这里只声明 `text` 与 `image`;要加 `video` 必须先有真正的读取器(对照 Kimi Code 线路的 `video-store.ts`);
|
|
195
195
|
- **瞬时失败按错误类别重试**(`src/host/minimax-code/adapter.ts`):上游模型供应商临时不可用(5xx)归为 `SERVER`、429 归为 `RATE_LIMIT`、连接未产出响应归为 `TRANSPORT`,走 DSH retry policy 的有界退避(最多 3 次,1.5s 起步、15s 上限、0.2 抖动);**但 429 的正文若说的是余额/额度耗尽,则判为终局**——重试只会推迟用户真正需要看到的提示;
|
|
196
196
|
- **401 会强制续期一次再重试**:本地时钟看着还有效、服务端却拒收的令牌(在桌面端被撤销、时钟偏移、桌面端已轮换)与「真的需要重新登录」在状态码上无法区分,所以第一次 401 会**强制刷新一次并原样重试同一个请求体**;重试再被拒才是终局;
|
package/lib/client.js
CHANGED
|
@@ -15158,6 +15158,45 @@ window.__ModuleLoader__.load({
|
|
|
15158
15158
|
if (last < text.length) nodes.push(text.slice(last));
|
|
15159
15159
|
return nodes;
|
|
15160
15160
|
}
|
|
15161
|
+
/** GFM 分隔行:至少一个 `-` 的单元格,形如 `| --- | :--: | ---: |`。 */
|
|
15162
|
+
const TABLE_SEPARATOR = /^\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)*\|?$/;
|
|
15163
|
+
/**
|
|
15164
|
+
* 一行表格 → 单元格数组。
|
|
15165
|
+
*
|
|
15166
|
+
* 先按未转义的 `|` 切,再剥掉首尾因为 `| a | b |` 这种写法留下的空单元;
|
|
15167
|
+
* `\|` 是单元格里的字面量竖线,切之前先换成占位符,切完再换回来。
|
|
15168
|
+
* @param line - 表格的一行原文。
|
|
15169
|
+
* @returns 去掉两侧空白的单元格。
|
|
15170
|
+
*/
|
|
15171
|
+
function splitRow(line) {
|
|
15172
|
+
const PH = "\0";
|
|
15173
|
+
const cells = line.replaceAll("\\|", PH).split("|").map((cell) => cell.replaceAll(PH, "|").trim());
|
|
15174
|
+
if (cells.length > 0 && cells[0] === "") cells.shift();
|
|
15175
|
+
if (cells.length > 0 && cells[cells.length - 1] === "") cells.pop();
|
|
15176
|
+
return cells;
|
|
15177
|
+
}
|
|
15178
|
+
/**
|
|
15179
|
+
* 分隔行的每个单元格 → 对齐方式。
|
|
15180
|
+
* @param line - 分隔行原文。
|
|
15181
|
+
* @returns 与列一一对应的对齐方式;缺省 left。
|
|
15182
|
+
*/
|
|
15183
|
+
function alignmentsOf(line) {
|
|
15184
|
+
return splitRow(line).map((cell) => {
|
|
15185
|
+
const left = cell.startsWith(":");
|
|
15186
|
+
const right = cell.endsWith(":");
|
|
15187
|
+
if (left && right) return "center";
|
|
15188
|
+
if (right) return "right";
|
|
15189
|
+
return "left";
|
|
15190
|
+
});
|
|
15191
|
+
}
|
|
15192
|
+
/**
|
|
15193
|
+
* 判断某一行是不是表格的分隔行(表格识别的前瞻条件之一)。
|
|
15194
|
+
* @param line - 待判定的行(已 trim)。
|
|
15195
|
+
* @returns 是分隔行则为 true。
|
|
15196
|
+
*/
|
|
15197
|
+
function isSeparator(line) {
|
|
15198
|
+
return line.includes("-") && TABLE_SEPARATOR.test(line);
|
|
15199
|
+
}
|
|
15161
15200
|
/**
|
|
15162
15201
|
* 把正文切成块。
|
|
15163
15202
|
* @param source - Markdown 原文。
|
|
@@ -15176,13 +15215,42 @@ window.__ModuleLoader__.load({
|
|
|
15176
15215
|
}
|
|
15177
15216
|
};
|
|
15178
15217
|
const lastBlock = () => blocks[blocks.length - 1];
|
|
15179
|
-
|
|
15180
|
-
|
|
15218
|
+
const rows = source.replaceAll("\r\n", "\n").split("\n");
|
|
15219
|
+
for (let index = 0; index < rows.length; index += 1) {
|
|
15220
|
+
const line = rows[index].trimEnd();
|
|
15181
15221
|
const trimmed = line.trim();
|
|
15182
15222
|
if (trimmed === "") {
|
|
15183
15223
|
flushParagraph();
|
|
15184
15224
|
continue;
|
|
15185
15225
|
}
|
|
15226
|
+
/**
|
|
15227
|
+
* 表格必须**在当前行前瞻两行**才认:本行是表头、下一行是分隔行、两侧管道符
|
|
15228
|
+
* 数目对得上。只凭「这行有 |」不行——普通正文里一个竖线不该把后文变成表格。
|
|
15229
|
+
*/
|
|
15230
|
+
const next = index + 1 < rows.length ? rows[index + 1].trim() : "";
|
|
15231
|
+
if (trimmed.includes("|") && isSeparator(next)) {
|
|
15232
|
+
const header = splitRow(trimmed);
|
|
15233
|
+
const aligns = alignmentsOf(next);
|
|
15234
|
+
if (header.length > 0) {
|
|
15235
|
+
flushParagraph();
|
|
15236
|
+
const body = [];
|
|
15237
|
+
index += 2;
|
|
15238
|
+
while (index < rows.length) {
|
|
15239
|
+
const rowLine = rows[index].trim();
|
|
15240
|
+
if (rowLine === "" || !rowLine.includes("|")) break;
|
|
15241
|
+
body.push(splitRow(rowLine));
|
|
15242
|
+
index += 1;
|
|
15243
|
+
}
|
|
15244
|
+
index -= 1;
|
|
15245
|
+
blocks.push({
|
|
15246
|
+
kind: "table",
|
|
15247
|
+
header,
|
|
15248
|
+
aligns,
|
|
15249
|
+
rows: body
|
|
15250
|
+
});
|
|
15251
|
+
continue;
|
|
15252
|
+
}
|
|
15253
|
+
}
|
|
15186
15254
|
const heading = /^(#{1,3})\s+(.*)$/.exec(trimmed);
|
|
15187
15255
|
if (heading !== null) {
|
|
15188
15256
|
flushParagraph();
|
|
@@ -15237,6 +15305,45 @@ window.__ModuleLoader__.load({
|
|
|
15237
15305
|
},
|
|
15238
15306
|
children: renderInline(block.text, key)
|
|
15239
15307
|
}, key);
|
|
15308
|
+
if (block.kind === "table") {
|
|
15309
|
+
/** 单元格:行内标记照常解析,对齐落到 style 上(表格里没有 class 可挂)。 */
|
|
15310
|
+
const cellStyle = (column) => ({
|
|
15311
|
+
textAlign: block.aligns[column] ?? "left",
|
|
15312
|
+
padding: "3px 8px",
|
|
15313
|
+
verticalAlign: "top"
|
|
15314
|
+
});
|
|
15315
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
15316
|
+
"data-dsh-part": "md-table-wrap",
|
|
15317
|
+
style: {
|
|
15318
|
+
overflowX: "auto",
|
|
15319
|
+
margin: "6px 0"
|
|
15320
|
+
},
|
|
15321
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
|
|
15322
|
+
"data-dsh-part": "md-table",
|
|
15323
|
+
style: {
|
|
15324
|
+
borderCollapse: "collapse",
|
|
15325
|
+
fontSize: "12px",
|
|
15326
|
+
lineHeight: "1.5"
|
|
15327
|
+
},
|
|
15328
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", { children: block.header.map((cell, column) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
|
|
15329
|
+
"data-dsh-part": "md-th",
|
|
15330
|
+
style: {
|
|
15331
|
+
...cellStyle(column),
|
|
15332
|
+
borderBottom: "1px solid var(--dsw-alias-border-l2, rgb(0 0 0 / 15%))",
|
|
15333
|
+
fontWeight: 600
|
|
15334
|
+
},
|
|
15335
|
+
children: renderInline(cell, key + "-h" + String(column))
|
|
15336
|
+
}, key + "-h" + String(column))) }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: block.rows.map((row, rowIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", { children: block.header.map((_, column) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
|
|
15337
|
+
"data-dsh-part": "md-td",
|
|
15338
|
+
style: {
|
|
15339
|
+
...cellStyle(column),
|
|
15340
|
+
borderBottom: "1px solid var(--dsw-alias-border-l3, rgb(0 0 0 / 7%))"
|
|
15341
|
+
},
|
|
15342
|
+
children: renderInline(row[column] ?? "", key + "-r" + String(rowIndex) + "-" + String(column))
|
|
15343
|
+
}, key + "-r" + String(rowIndex) + "-" + String(column))) }, key + "-r" + String(rowIndex))) })]
|
|
15344
|
+
})
|
|
15345
|
+
}, key);
|
|
15346
|
+
}
|
|
15240
15347
|
if (block.kind === "ul" || block.kind === "ol") {
|
|
15241
15348
|
const items = block.items.map((item, itemIndex) => {
|
|
15242
15349
|
const itemKey = key + "-" + String(itemIndex);
|
|
@@ -15766,9 +15873,15 @@ window.__ModuleLoader__.load({
|
|
|
15766
15873
|
lineHeight: "1.5",
|
|
15767
15874
|
color: "var(--dsw-alias-label-tertiary, #8a9099)"
|
|
15768
15875
|
};
|
|
15769
|
-
/**
|
|
15876
|
+
/**
|
|
15877
|
+
* 正文样式:只管外边距、字号与颜色。
|
|
15878
|
+
*
|
|
15879
|
+
* **不再**在这里写 `whiteSpace: 'pre-wrap'`:正文交给 {@link MarkdownLite} 渲染,
|
|
15880
|
+
* 换行该不该保留由它产出的块级元素决定。早先这里是纯文本 `<p>{message}</p>`,
|
|
15881
|
+
* 于是列表符号、`**粗体**` 和管道符表格全部原样上屏 —— 同一份进展在侧栏面板里
|
|
15882
|
+
* 是渲染过的、在对话流里是原文,两处观感对不上。
|
|
15883
|
+
*/
|
|
15770
15884
|
const messageStyle = {
|
|
15771
|
-
whiteSpace: "pre-wrap",
|
|
15772
15885
|
overflowWrap: "anywhere",
|
|
15773
15886
|
margin: "0",
|
|
15774
15887
|
fontSize: "12px",
|
|
@@ -15868,10 +15981,10 @@ window.__ModuleLoader__.load({
|
|
|
15868
15981
|
children: translate(STATE_KEYS[state])
|
|
15869
15982
|
})
|
|
15870
15983
|
]
|
|
15871
|
-
}), expanded && message !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
15984
|
+
}), expanded && message !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
15872
15985
|
"data-dsh-part": "progress-row-message",
|
|
15873
15986
|
style: messageStyle,
|
|
15874
|
-
children: message
|
|
15987
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MarkdownLite, { text: message })
|
|
15875
15988
|
})]
|
|
15876
15989
|
});
|
|
15877
15990
|
}
|