@eddyskywalker/dsh-chatgpt-subscription 0.43.1 → 0.44.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 +16 -0
- package/cordis.patch.yml +5 -0
- package/lib/client.js +81 -8
- package/lib/client.js.map +1 -1
- package/lib/entry-progress-updates-CkGJr_fe.js +1004 -0
- package/lib/index.js +44 -970
- package/lib/progress-updates.js +2 -0
- package/lib/types/client/progress-updates/host-source.d.ts +16 -0
- package/lib/types/client/progress-updates/host-source.d.ts.map +1 -1
- package/lib/types/client/progress-updates/index.d.ts.map +1 -1
- package/lib/types/client/progress-updates/settings-binding.d.ts +5 -0
- package/lib/types/client/progress-updates/settings-binding.d.ts.map +1 -1
- package/lib/types/compat.d.ts +1 -1
- package/lib/types/entry-progress-updates.d.ts +43 -0
- package/lib/types/entry-progress-updates.d.ts.map +1 -0
- package/lib/types/host/proxy-manager.d.ts +6 -0
- package/lib/types/host/proxy-manager.d.ts.map +1 -1
- package/lib/types/index.d.ts +21 -25
- package/lib/types/index.d.ts.map +1 -1
- package/locale/progress-updates/en.json +6 -0
- package/locale/progress-updates/zh.json +6 -0
- package/package.json +13 -3
- package/progress-updates.svg +9 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.44.0 - 2026-10-27
|
|
6
|
+
|
|
7
|
+
- **[packaging] 「进展更新」拆成独立组件:同包第二行,可在插件管理页单独关闭**
|
|
8
|
+
- **机制**:`cordis.patch.yml` 现在插两行 loader 条目;新增 `src/entry-progress-updates.ts` 作为第二个宿主入口(自带 `Config`、`inject` 与 `apply`),`package.json` 增加 `exports["./progress-updates"]` 与子路径行的 `locale/*.json` / `icon`,构建多入口产出 `lib/progress-updates.js`。管理页的「包含的组件」因此从 1 变成 2。
|
|
9
|
+
- **设置字段留在核心行**:三个 `volatile` 字段仍声明在 `src/index.ts` 的 `Config`,由核心在 `apply` 时通过 `attachProgressSettings()` 把读取器交给新行(两行的挂载顺序两种都兜住)。不能搬走的原因很实在:profile 的 patch 层按 id 定位**替换整行 config**,而用户 profile 早就在核心行写了 `progressUpdates: true`——字段搬去新行,那条 patch 会把新行配置整体抹掉、schema 默认值填回 false,于是「设置显示打开、实际是关的」。
|
|
10
|
+
- **前端自隐**:同包多行只拆宿主——浏览器半边仍按包加载。客户端挂载时探一次 `GET api/dsh-progress-updates/updates`:**只有路由自己回的 JSON 404/405** 才说明那一行没装(网关兜底的纯文本 `not found` 也是 404,第一版据此把装着它的实例的 UI 也撤了),网络错误按「装着」处理。
|
|
11
|
+
- **回归**:`progress-updates-live-ref-and-route` 改为读新入口的 `Config`;新增 3 例(宿主不在时撤注册、宿主在时不动、探测失败按装着);`minimax-media-tool-registration` 改为断言 `progress_update` 不再属于核心行。
|
|
12
|
+
- **验证**:`npm run typecheck` 0 错误;全量 Vitest **4906 passed / 10 skipped**(唯一失败仍是 GLM adopt 那个环境用例);`npm run build` 产出 `lib/index.js` + `lib/progress-updates.js`;`npm pack --dry-run` 含 `lib/progress-updates.js`、`locale/progress-updates/{zh,en}.json`、`progress-updates.svg`;直接 import 构建产物确认 `name / apply / Config` 三项齐全、默认值解析为 `true / 8 / auto`。
|
|
13
|
+
- **未验证**:插件管理页上真的出现两个开关需要重启 DSH(bundle patch 在启动时应用),本轮没有重启你的实例。
|
|
14
|
+
|
|
15
|
+
- **[proxy] 代理连接池被销毁不再让回答卡死:死连接自动换新,卸载时优雅关闭**
|
|
16
|
+
- **现象**:长思考进行到一半,界面出现「已重试模型请求(1/3)」与 `terminated: The client is destroyed`,随后「已停止」。与 0.43.0 修的 180 秒超时是两个不同的故障。
|
|
17
|
+
- **为什么**:`terminated` 是 undici 的包装错误,`The client is destroyed` 是它的 `ClientDestroyedError`——请求还在流式读取时,脚下的连接池已经不存在了。这条线还有两处会把「一次事故」放大成「持续故障」:`ProxyManager.dispose()` 用 `destroy()` 立刻拆连接(任何插件卸载都会掐断在途回答),以及被销毁的 agent 仍留在按 URL 缓存的表里,之后每个请求都复用它并在瞬间失败。
|
|
18
|
+
- **改法**:卸载改为 `close()`——等在建请求跑完再释放 socket;代理请求遇到 destroyed-client 家族的错误时,把该 URL 的缓存 agent 摘掉、换一个新连接**重试一次**;错误判定只认这一族,普通的连接失败仍然不重放(那是另一种决定)。
|
|
19
|
+
- **测试**:`test/proxy-manager.test.ts` 新增两例——销毁后换新连接并成功(断言第二次的 dispatcher 不是第一次那个)、普通传输失败只跑一次。
|
|
20
|
+
|
|
5
21
|
## 0.43.1 - 2026-10-27
|
|
6
22
|
|
|
7
23
|
- **[qoder] 上游排队不再被说成「API 密钥无效」;额度用尽与排队分成两条路**
|
package/cordis.patch.yml
CHANGED
|
@@ -4,3 +4,8 @@
|
|
|
4
4
|
- insert:
|
|
5
5
|
- id: dsh-chatgpt-subscription
|
|
6
6
|
name: '@eddyskywalker/dsh-chatgpt-subscription'
|
|
7
|
+
# 第二个组件:「进展更新」。同包多行 = 两个独立的 loader 条目,管理页各有一
|
|
8
|
+
# 个开关;浏览器半边仍只有一份 bundle(`dsh.client` 按包声明),所以它自己
|
|
9
|
+
# 探测这一行的路由在不在,不在就不注册面板与设置分区。
|
|
10
|
+
- id: dsh-chatgpt-subscription-progress-updates
|
|
11
|
+
name: '@eddyskywalker/dsh-chatgpt-subscription/progress-updates'
|
package/lib/client.js
CHANGED
|
@@ -53423,6 +53423,44 @@ window.__ModuleLoader__.load({
|
|
|
53423
53423
|
* (同 dsh-usage / dsh-git-graph 的处理)。
|
|
53424
53424
|
*/
|
|
53425
53425
|
const PROGRESS_UPDATES_PATH = "api/dsh-progress-updates/updates";
|
|
53426
|
+
/**
|
|
53427
|
+
* 宿主那一行今天装没装。
|
|
53428
|
+
*
|
|
53429
|
+
* 这个包的浏览器半边按**包**加载:即使「进展更新」那一行被关掉,本 bundle 照样
|
|
53430
|
+
* 会跑,面板与设置分区就会变成两个永远空的壳。所以挂载前问一次宿主的只读路由。
|
|
53431
|
+
*
|
|
53432
|
+
* **只在路由自己说不存在时判「没装」**:本路由的 403(非 loopback)与 200 都说明
|
|
53433
|
+
* 它在;而网关对一个不认识的路径回的那句 `not found`(纯文本或 HTML)也常常是
|
|
53434
|
+
* 404,把「任何 404」当成没装会让装着它的实例把 UI 自己撤掉——第一版就是这么写的,
|
|
53435
|
+
* 实测踩到了。
|
|
53436
|
+
*
|
|
53437
|
+
* 探测失败(网络错误、超时、无法判断)一律按「装着」处理:宁可多一格外壳,也不能
|
|
53438
|
+
* 因为一次抖动把装着的功能判成没装。
|
|
53439
|
+
* @returns 宿主半边是否在线。
|
|
53440
|
+
*/
|
|
53441
|
+
async function isProgressUpdatesHostPresent() {
|
|
53442
|
+
if (typeof fetch !== "function") return true;
|
|
53443
|
+
let response;
|
|
53444
|
+
try {
|
|
53445
|
+
response = await fetch(PROGRESS_UPDATES_PATH, {
|
|
53446
|
+
method: "GET",
|
|
53447
|
+
headers: { accept: "application/json" }
|
|
53448
|
+
});
|
|
53449
|
+
} catch {
|
|
53450
|
+
return true;
|
|
53451
|
+
}
|
|
53452
|
+
if (response.status !== 404 && response.status !== 405) return true;
|
|
53453
|
+
if (!(response.headers.get("content-type") ?? "").toLowerCase().includes("json")) return true;
|
|
53454
|
+
let body;
|
|
53455
|
+
try {
|
|
53456
|
+
body = await response.json();
|
|
53457
|
+
} catch {
|
|
53458
|
+
return true;
|
|
53459
|
+
}
|
|
53460
|
+
if (body === null || typeof body !== "object") return true;
|
|
53461
|
+
const ok = body.ok;
|
|
53462
|
+
return typeof ok === "boolean" ? ok : true;
|
|
53463
|
+
}
|
|
53426
53464
|
/** 默认定时器:直接转发到 `globalThis`(浏览器与 Node 都能跑)。 */
|
|
53427
53465
|
const DEFAULT_TIMERS = {
|
|
53428
53466
|
setInterval: (handler, ms) => globalThis.setInterval(handler, ms),
|
|
@@ -53644,6 +53682,11 @@ window.__ModuleLoader__.load({
|
|
|
53644
53682
|
* 第一项来自 `cordis.patch.yml` 的行 id(独立安装的唯一形态);后两项是聚合安装
|
|
53645
53683
|
* 可能套的前缀。镜像答上来之后不再用这张表的顺序,改用"值里带 `progressUpdates`
|
|
53646
53684
|
* 的那一条"。
|
|
53685
|
+
*
|
|
53686
|
+
* 这三个字段挂在**核心那一行**(`src/index.ts` 的 Config)而不是「进展更新」那一行:
|
|
53687
|
+
* 用户/profile 早就在核心行的 config 里写过 `progressUpdates`,而 loader 的 profile
|
|
53688
|
+
* 层是按 id 替换整行 config 的——字段若搬去新行,profile 一写就等于把那行的开关
|
|
53689
|
+
* 抹成默认值,于是「设置里显示打开」和「实际是关的」同时成立。
|
|
53647
53690
|
*/
|
|
53648
53691
|
const PROGRESS_SETTINGS_ENTRY_IDS = [
|
|
53649
53692
|
"dsh-chatgpt-subscription",
|
|
@@ -53684,6 +53727,10 @@ window.__ModuleLoader__.load({
|
|
|
53684
53727
|
}
|
|
53685
53728
|
/**
|
|
53686
53729
|
* 判断一个条目的解析值是不是本插件的 Config 切片。
|
|
53730
|
+
*
|
|
53731
|
+
* 按**键**认领而不是按行 id:聚合安装会给条目套家族前缀,而字段名是唯一稳定的。
|
|
53732
|
+
* 认领对象是核心行(进度更新的实现行现在没有这些字段了),所以「值里带
|
|
53733
|
+
* `progressUpdates` 的那一条」就正好是设置该写进去的那一条。
|
|
53687
53734
|
* @param value - describe 交来的解析值。
|
|
53688
53735
|
* @returns 是否带 `progressUpdates` 这个键。
|
|
53689
53736
|
*/
|
|
@@ -53857,6 +53904,28 @@ window.__ModuleLoader__.load({
|
|
|
53857
53904
|
*/
|
|
53858
53905
|
const explicitSource = options.source;
|
|
53859
53906
|
/**
|
|
53907
|
+
* 宿主那一行是不是装着。
|
|
53908
|
+
*
|
|
53909
|
+
* 同包多组件之后,关掉「进展更新」只会卸掉宿主那一行:浏览器半边仍随本包的
|
|
53910
|
+
* bundle 加载,面板与设置分区就会变成永远空的壳。启动时问一次宿主的只读路由,
|
|
53911
|
+
* 缺了就撤掉已经注册的槽位、并且不再响应后续出现的槽位。
|
|
53912
|
+
*
|
|
53913
|
+
* 显式给了数据源(测试与将来替换实现)时不探测:那时宿主根本不在链路里。
|
|
53914
|
+
*/
|
|
53915
|
+
let hostPresent = true;
|
|
53916
|
+
const registrations = [];
|
|
53917
|
+
const keep = (dispose) => {
|
|
53918
|
+
registrations.push(dispose);
|
|
53919
|
+
return dispose;
|
|
53920
|
+
};
|
|
53921
|
+
if (explicitSource === void 0) isProgressUpdatesHostPresent().then((present) => {
|
|
53922
|
+
if (present) return;
|
|
53923
|
+
hostPresent = false;
|
|
53924
|
+
for (const dispose of registrations.splice(0)) try {
|
|
53925
|
+
dispose();
|
|
53926
|
+
} catch {}
|
|
53927
|
+
});
|
|
53928
|
+
/**
|
|
53860
53929
|
* 默认数据源:每个会话一份轮询源。
|
|
53861
53930
|
*
|
|
53862
53931
|
* 槽位是 session 作用域的,同一个页签在会话切换时会被重新注入一次;按会话 id
|
|
@@ -53981,37 +54050,40 @@ window.__ModuleLoader__.load({
|
|
|
53981
54050
|
* 这是本特写的主形态——不依赖侧栏,也不依赖宿主路由,只看工具调用的参数。
|
|
53982
54051
|
*/
|
|
53983
54052
|
ctx.slots.inject("tool.call.toolview", () => {
|
|
54053
|
+
if (!hostPresent) return () => {};
|
|
53984
54054
|
try {
|
|
53985
|
-
return ctx.slots.register({
|
|
54055
|
+
return keep(ctx.slots.register({
|
|
53986
54056
|
name: "tool.call.toolview",
|
|
53987
54057
|
key: PROGRESS_UPDATE_TOOL_NAME,
|
|
53988
54058
|
locale: NS_PROGRESS_UPDATES
|
|
53989
|
-
}, ProgressRow);
|
|
54059
|
+
}, ProgressRow));
|
|
53990
54060
|
} catch {
|
|
53991
54061
|
return () => {};
|
|
53992
54062
|
}
|
|
53993
54063
|
});
|
|
53994
54064
|
/** 阶段二:同一个 id 下渲染页签正文。 */
|
|
53995
54065
|
ctx.slots.inject("sidebar.right.pane.tab", () => {
|
|
54066
|
+
if (!hostPresent) return () => {};
|
|
53996
54067
|
try {
|
|
53997
|
-
return ctx.slots.register({
|
|
54068
|
+
return keep(ctx.slots.register({
|
|
53998
54069
|
name: "sidebar.right.pane.tab",
|
|
53999
54070
|
key: PANEL_TAB_ID,
|
|
54000
54071
|
locale: NS_PROGRESS_UPDATES,
|
|
54001
54072
|
inject: (sessionId) => ({ source: explicitSource ?? hostSourceOf(sessionId) })
|
|
54002
|
-
}, ProgressUpdatesTab);
|
|
54073
|
+
}, ProgressUpdatesTab));
|
|
54003
54074
|
} catch {
|
|
54004
54075
|
return () => {};
|
|
54005
54076
|
}
|
|
54006
54077
|
});
|
|
54007
54078
|
/** 阶段二:同一个 id 下渲染页签条上的标题。 */
|
|
54008
54079
|
ctx.slots.inject("sidebar.right.pane.tab.title", () => {
|
|
54080
|
+
if (!hostPresent) return () => {};
|
|
54009
54081
|
try {
|
|
54010
|
-
return ctx.slots.register({
|
|
54082
|
+
return keep(ctx.slots.register({
|
|
54011
54083
|
name: "sidebar.right.pane.tab.title",
|
|
54012
54084
|
key: PANEL_TAB_ID,
|
|
54013
54085
|
locale: NS_PROGRESS_UPDATES
|
|
54014
|
-
}, ProgressUpdatesTabTitle);
|
|
54086
|
+
}, ProgressUpdatesTabTitle));
|
|
54015
54087
|
} catch {
|
|
54016
54088
|
return () => {};
|
|
54017
54089
|
}
|
|
@@ -54022,9 +54094,10 @@ window.__ModuleLoader__.load({
|
|
|
54022
54094
|
* 没有这一格,面板就是注册好了也永远点不开——类型和正文都不会自己长出入口。
|
|
54023
54095
|
*/
|
|
54024
54096
|
ctx.slots.inject("settings.section", () => {
|
|
54097
|
+
if (!hostPresent) return () => {};
|
|
54025
54098
|
try {
|
|
54026
54099
|
const openPanel = openPanelAction(ctx, options.openPanel);
|
|
54027
|
-
return ctx.slots.register({
|
|
54100
|
+
return keep(ctx.slots.register({
|
|
54028
54101
|
name: "settings.section",
|
|
54029
54102
|
id: SETTINGS_SECTION_ID,
|
|
54030
54103
|
order: 150,
|
|
@@ -54043,7 +54116,7 @@ window.__ModuleLoader__.load({
|
|
|
54043
54116
|
settings: currentSettings
|
|
54044
54117
|
};
|
|
54045
54118
|
}
|
|
54046
|
-
}, ProgressUpdatesSettingsSection);
|
|
54119
|
+
}, ProgressUpdatesSettingsSection));
|
|
54047
54120
|
} catch {
|
|
54048
54121
|
return () => {};
|
|
54049
54122
|
}
|