@eddyskywalker/dsh-chatgpt-subscription 0.15.0 → 0.16.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 +14 -0
- package/README.md +2 -0
- package/lib/client.js +69 -10
- package/lib/client.js.map +1 -1
- package/lib/index.js +105 -0
- package/lib/types/client/workbuddy/WorkBuddySection.d.ts +36 -0
- package/lib/types/client/workbuddy/WorkBuddySection.d.ts.map +1 -1
- package/lib/types/client/workbuddy/locales.d.ts +18 -0
- package/lib/types/client/workbuddy/locales.d.ts.map +1 -1
- package/lib/types/host/workbuddy/client.d.ts +8 -0
- package/lib/types/host/workbuddy/client.d.ts.map +1 -1
- package/lib/types/host/workbuddy/model-catalog.d.ts +30 -1
- package/lib/types/host/workbuddy/model-catalog.d.ts.map +1 -1
- package/lib/types/host/workbuddy/routes.d.ts +7 -0
- package/lib/types/host/workbuddy/routes.d.ts.map +1 -1
- package/lib/types/shared/workbuddy-contracts.d.ts +42 -0
- package/lib/types/shared/workbuddy-contracts.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.16.0 - 2026-10-09
|
|
6
|
+
|
|
7
|
+
- **[WorkBuddy] 模型行加上消耗倍率提示**
|
|
8
|
+
- **倍率一直是公开的,只是本插件没读。** 网关 `GET /v3/config` 每个模型条目都带一个 `credits` 字符串(国际区 `x6.67`、国区 `x0.79 credits`),就是该模型消耗套餐额度的相对速率;官方 CodeBuddy 客户端把同一个字段渲染成 `6.67x` 显示在模型下拉里(其 web-ui 里对应的就是 `credits.replace(/\s*credits$/i,'').replace(/^[x×]/i,'') + 'x'`)。
|
|
9
|
+
- **倍率必须按区域存,不能一个 id 一个数。** 实测 2026-10-09:`deepseek-v4.1-flash` 国区 `0.11`、国际区 `0.00`——一个标量必然对其中一个区的账号是错的。因此 `credits` 是 `Partial<Record<WorkBuddyRegion, string>>`,**只为该区确实公布过的值写键**;两区共有的 8 个 id 里 7 个数值一致、1 个不一致。
|
|
10
|
+
- **实时目录必须解析这个字段,兜底表也要抄。** 网关可达时**整表替换**内置表,若只在兜底表里写倍率,登录用户反而永远看不到它,而且上游一改价本地就一直是错的。两处都写上。
|
|
11
|
+
- **未公布的倍率一律不出现在界面上,而不是显示 0。** `default-model` 公布的是空字符串;`x0.00` 是**真实声明**(该模型不消耗额度),两者必须区分开——所以在 host 侧就把空串解析成「字段缺席」,`0.00` 原样保留。在一个花钱的数字上猜一个值,比缺一个值更糟。
|
|
12
|
+
- **账号区域已知时只显示该区的值,绝不拿另一个区顶上**;区域未知(还没读回账号)而两区不一致时把两区都写出来(`倍率 0.11x(国区) / 0.00x(国际区)`),一致时折叠成一个值。**两区域串的每一个字都由字典提供**——区域名词、括号字形、连两段之间的分隔符都是模板键,函数里不硬拼任何一个;中英括号字形不同(全角自带留白、半角不带),硬拼必然有一侧把 `(China)/ 0.00x` 粘成一段。跨区调用本来就会被上游以 400 `code 11102` 拒绝,所以借用邻区的数字等于报一个这个账号永远不会付的价。
|
|
13
|
+
- 倍率接在提示行**末尾**(`1M · 图片 · low/high/max · 倍率 0.79x`):容量/图像/档位说的是模型**接受什么**,倍率说的是它**花多少钱**,把花钱那条留在最后,前面的能力信息仍读作一个短语。没有倍率时该项**整个不出现**,不留占位、不产生连续两个 `·`。
|
|
14
|
+
- **区域裁剪放在客户端而不是 host**:`buildModelOptions` 返回的 DTO 也会在没有账号的情况下被读取(harness 在未选定凭据时就解析模型列表),host 侧裁掉会让那种调用方拿到空值。
|
|
15
|
+
- 三处边界由测试钉住:`'×3.31'`/`' x1.62 credits '` 这类拼写、`'x0.00'` 必须保留、`''`/`'0.5x'`/`'x1,000'`/`null`/`42` 必须解析成 null(而不是 0)。另加一条全表不变量:`FALLBACK_MODELS` 里每个 `credits` 键都必须是该条自己 `regions` 声明过的区域。
|
|
16
|
+
- 测试:新增 `creditMultiplierHint` 的逐规则用例(含双语)、`parseConfigModels`/`buildModelOptions` 的透传用例、模型行的渲染级断言与「无倍率不留分隔符」用例。
|
|
17
|
+
- 验证:`npm run typecheck` 0 错误;全量 `npm test` **2909 passed / 7 skipped**(较基线 2886 增 23 例,0 failed)。倍率数值本身由一次性探针 `scripts/probe-workbuddy-credits.probe.ts` 从实时 `/v3/config` 读出,`FALLBACK_MODELS` 的 43 行倍率与实测**逐字一致**(另 4 行网关未公布,故无该字段),且探针复核出「两区不一致的只有 `deepseek-v4.1-flash` 一个 id」。
|
|
18
|
+
|
|
5
19
|
## 0.15.0 - 2026-10-09
|
|
6
20
|
|
|
7
21
|
- **[WorkBuddy] 补上网关「在服务但从不公布」的模型,并按厂商归拢模型列表**
|
package/README.md
CHANGED
|
@@ -586,6 +586,8 @@ DSH 设置页的「Subagent」卡片会把勾选的模型写成会话级的允
|
|
|
586
586
|
|
|
587
587
|
`workbuddy-subscription` 会像其他 Provider 一样出现在 DSH 模型选择器中,并可与名为 `workbuddy` 的自定义 API 同时存在。**上下文窗口**默认取网关 `/v3/config` 声明的**默认服务长度**,可逐模型覆盖(用于 DSH 的压缩与溢出判断,支持 `1M` / `300K` / `200000` 等写法);**默认思考深度**逐模型生效,选项由当前账号各模型**实际声明的档位**取并集(仅部分模型支持的档位会标注数量),档位不在该模型集合内时不会被发送。
|
|
588
588
|
|
|
589
|
+
**消耗倍率**也来自同一份目录:每个模型在 `/v3/config` 里带一个 `credits` 字符串(如 `x0.79 credits`、`x6.67`),就是该模型消耗套餐额度的相对速率——官方 CodeBuddy 客户端把它渲染成 `6.67x` 显示在模型下拉里。设置页的模型行末尾会以 `倍率 0.79x` 的形式给出,**两区不一致时把两区都写出来**(实测国际区 `deepseek-v4.1-flash` 是 `0.00`、国区是 `0.11`),账号区域已知时只显示该区的值,**绝不拿另一个区的数字顶上**(跨区调用本来就会被上游以 400 `code 11102` 拒绝)。`x0.00` 是真实声明(该模型不消耗额度),照常显示;网关没给倍率的模型(如 `default-model`)则**整项不出现在提示里**,而不是编一个 0。
|
|
590
|
+
|
|
589
591
|
**凭据目录**按平台解析,可用 `CODEBUDDY_AUTH_DIR` 覆盖(与官方工具链一致):
|
|
590
592
|
|
|
591
593
|
| 平台 | 默认目录 |
|
package/lib/client.js
CHANGED
|
@@ -5009,6 +5009,9 @@ window.__ModuleLoader__.load({
|
|
|
5009
5009
|
unselectAll: "全不选",
|
|
5010
5010
|
imageSupport: "图片",
|
|
5011
5011
|
textOnly: "纯文本",
|
|
5012
|
+
creditMultiplier: "倍率",
|
|
5013
|
+
creditMultiplierRegion: "{value}({region})",
|
|
5014
|
+
creditMultiplierPair: "{first} / {second}",
|
|
5012
5015
|
regionBadge: "区域",
|
|
5013
5016
|
unavailableHere: "当前区域不可用",
|
|
5014
5017
|
enhanced: "增强功能",
|
|
@@ -5092,6 +5095,9 @@ window.__ModuleLoader__.load({
|
|
|
5092
5095
|
unselectAll: "Deselect all",
|
|
5093
5096
|
imageSupport: "Images",
|
|
5094
5097
|
textOnly: "Text only",
|
|
5098
|
+
creditMultiplier: "Multiplier",
|
|
5099
|
+
creditMultiplierRegion: "{value} ({region})",
|
|
5100
|
+
creditMultiplierPair: "{first} / {second}",
|
|
5095
5101
|
regionBadge: "Regions",
|
|
5096
5102
|
unavailableHere: "Unavailable in this region",
|
|
5097
5103
|
enhanced: "Enhanced features",
|
|
@@ -5648,6 +5654,51 @@ window.__ModuleLoader__.load({
|
|
|
5648
5654
|
xhigh: "X-High",
|
|
5649
5655
|
max: "Max"
|
|
5650
5656
|
};
|
|
5657
|
+
/**
|
|
5658
|
+
* The consumption rate of one model, as the settings row states it.
|
|
5659
|
+
*
|
|
5660
|
+
* The gateway publishes one rate per region and the official CodeBuddy picker
|
|
5661
|
+
* spells it beside a model as `6.67x`; the row uses the same shape behind the
|
|
5662
|
+
* section's own label. Which rates reach the row depends on what the card knows
|
|
5663
|
+
* about the account, and the two cases are deliberately different:
|
|
5664
|
+
*
|
|
5665
|
+
* - A KNOWN region shows that region's rate and nothing else. Borrowing the
|
|
5666
|
+
* sibling region's number would state a price this account never pays —
|
|
5667
|
+
* measured 2026-10-09, `deepseek-v4.1-flash` is `0.11` on cn against `0.00`
|
|
5668
|
+
* on intl, and the backends reject a model asked of the wrong region anyway.
|
|
5669
|
+
* - An UNKNOWN region (no account read back yet) shows both rates when the
|
|
5670
|
+
* backends disagree, so the row is honest about the range instead of picking
|
|
5671
|
+
* one of them. When they agree there is nothing to disambiguate.
|
|
5672
|
+
*
|
|
5673
|
+
* The two-region form is assembled entirely from the caller's labels: the
|
|
5674
|
+
* qualifier comes from `labels.region(value, key)` and the join from
|
|
5675
|
+
* `labels.pair(first, second)`, so the dictionary owns the region nouns, the
|
|
5676
|
+
* bracket glyphs AND the separator. Nothing about the two-region string is
|
|
5677
|
+
* spelled in this file, which is the point — the glyphs differ per language
|
|
5678
|
+
* (`倍率 0.11x(国区) / 0.00x(国际区)` in Chinese,
|
|
5679
|
+
* `Multiplier 0.11x (China) / 0.00x (International)` in English) and a
|
|
5680
|
+
* separator chosen here would be right in at most one of them.
|
|
5681
|
+
*
|
|
5682
|
+
* `null` means "this row states no rate"; the caller drops it from the hint
|
|
5683
|
+
* array rather than rendering a placeholder, because a guessed rate on a spend
|
|
5684
|
+
* figure is worse than a missing one. `'0.00'` is a declaration — this model
|
|
5685
|
+
* consumes no allowance — so it renders like any other value.
|
|
5686
|
+
*/
|
|
5687
|
+
function creditMultiplierHint(credits, region, labels) {
|
|
5688
|
+
const rate = (key) => {
|
|
5689
|
+
const value = credits?.[key];
|
|
5690
|
+
return typeof value === "string" && value !== "" ? value : null;
|
|
5691
|
+
};
|
|
5692
|
+
if (region !== null) {
|
|
5693
|
+
const value = rate(region);
|
|
5694
|
+
return value === null ? null : `${labels.multiplier} ${value}x`;
|
|
5695
|
+
}
|
|
5696
|
+
const cn = rate("cn");
|
|
5697
|
+
const intl = rate("intl");
|
|
5698
|
+
if (cn === null) return intl === null ? null : `${labels.multiplier} ${intl}x`;
|
|
5699
|
+
if (intl === null || intl === cn) return `${labels.multiplier} ${cn}x`;
|
|
5700
|
+
return `${labels.multiplier} ${labels.pair(labels.region(`${cn}x`, "cn"), labels.region(`${intl}x`, "intl"))}`;
|
|
5701
|
+
}
|
|
5651
5702
|
/** Mask a UIN so the card shows identity without publishing the full number. */
|
|
5652
5703
|
function maskUin(uin) {
|
|
5653
5704
|
if (uin === void 0 || uin === null || uin === "") return "—";
|
|
@@ -5847,16 +5898,24 @@ window.__ModuleLoader__.load({
|
|
|
5847
5898
|
children: t.modelsHint
|
|
5848
5899
|
}),
|
|
5849
5900
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelChecklist, {
|
|
5850
|
-
items: (status?.models ?? []).map((model) =>
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
|
|
5901
|
+
items: (status?.models ?? []).map((model) => {
|
|
5902
|
+
const multiplier = creditMultiplierHint(model.credits, status?.account?.region ?? null, {
|
|
5903
|
+
multiplier: t.creditMultiplier,
|
|
5904
|
+
region: (value, key) => t.creditMultiplierRegion.replace("{value}", value).replace("{region}", key === "cn" ? t.regionCn : t.regionIntl),
|
|
5905
|
+
pair: (first, second) => t.creditMultiplierPair.replace("{first}", first).replace("{second}", second)
|
|
5906
|
+
});
|
|
5907
|
+
return {
|
|
5908
|
+
id: model.id,
|
|
5909
|
+
name: model.name,
|
|
5910
|
+
hint: [
|
|
5911
|
+
formatCapacity(model.contextWindow),
|
|
5912
|
+
model.supportsImage ? t.imageSupport : t.textOnly,
|
|
5913
|
+
...model.reasoningEfforts && model.reasoningEfforts.length > 0 ? [model.reasoningEfforts.join("/")] : [],
|
|
5914
|
+
...multiplier === null ? [] : [multiplier]
|
|
5915
|
+
].join(" · "),
|
|
5916
|
+
enabled: model.enabled
|
|
5917
|
+
};
|
|
5918
|
+
}),
|
|
5860
5919
|
busy: busy !== null,
|
|
5861
5920
|
onToggle: (id, enabled) => void toggleModel(id, enabled),
|
|
5862
5921
|
onToggleAll: (enabled) => void setAllModels(enabled),
|