@eddyskywalker/dsh-chatgpt-subscription 0.21.0 → 0.23.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 +46 -0
- package/README.md +56 -3
- package/lib/client.js +2719 -491
- package/lib/client.js.map +1 -1
- package/lib/index.js +8041 -3092
- package/lib/types/client/glm-coding-plan/GlmCodingPlanSection.d.ts.map +1 -1
- package/lib/types/client/glm-coding-plan/locales.d.ts +17 -26
- package/lib/types/client/glm-coding-plan/locales.d.ts.map +1 -1
- package/lib/types/client/glm-coding-plan/styles.d.ts +2 -2
- package/lib/types/client/glm-coding-plan/styles.d.ts.map +1 -1
- package/lib/types/client/hub/brand-icons.d.ts +2 -2
- package/lib/types/client/hub/brand-icons.d.ts.map +1 -1
- package/lib/types/client/hub/providers.d.ts.map +1 -1
- package/lib/types/client/index.d.ts +2 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/ollama/OllamaSection.d.ts.map +1 -1
- package/lib/types/client/ollama/api.d.ts +13 -0
- package/lib/types/client/ollama/api.d.ts.map +1 -1
- package/lib/types/client/ollama/locales.d.ts +24 -0
- package/lib/types/client/ollama/locales.d.ts.map +1 -1
- package/lib/types/client/step-code/StepCodeComposerQuota.d.ts +52 -0
- package/lib/types/client/step-code/StepCodeComposerQuota.d.ts.map +1 -0
- package/lib/types/client/step-code/StepCodeSection.d.ts +28 -0
- package/lib/types/client/step-code/StepCodeSection.d.ts.map +1 -0
- package/lib/types/client/step-code/api.d.ts +4 -0
- package/lib/types/client/step-code/api.d.ts.map +1 -0
- package/lib/types/client/step-code/locales.d.ts +648 -0
- package/lib/types/client/step-code/locales.d.ts.map +1 -0
- package/lib/types/client/step-code/styles.d.ts +28 -0
- package/lib/types/client/step-code/styles.d.ts.map +1 -0
- package/lib/types/client/step-code/useStepCodeSection.d.ts +122 -0
- package/lib/types/client/step-code/useStepCodeSection.d.ts.map +1 -0
- package/lib/types/host/antigravity/account-pool.d.ts.map +1 -1
- package/lib/types/host/common/account-pool.d.ts +38 -3
- package/lib/types/host/common/account-pool.d.ts.map +1 -1
- package/lib/types/host/common/model-request-control.d.ts +1 -1
- package/lib/types/host/common/model-request-control.d.ts.map +1 -1
- package/lib/types/host/common/request-diagnostics.d.ts +1 -1
- package/lib/types/host/common/request-diagnostics.d.ts.map +1 -1
- package/lib/types/host/glm-coding-plan/account-pool.d.ts.map +1 -1
- package/lib/types/host/glm-coding-plan/adapter.d.ts +1 -14
- package/lib/types/host/glm-coding-plan/adapter.d.ts.map +1 -1
- package/lib/types/host/glm-coding-plan/client.d.ts.map +1 -1
- package/lib/types/host/glm-coding-plan/types.d.ts +0 -10
- package/lib/types/host/glm-coding-plan/types.d.ts.map +1 -1
- package/lib/types/host/ollama/adapter.d.ts +26 -2
- package/lib/types/host/ollama/adapter.d.ts.map +1 -1
- package/lib/types/host/ollama/client.d.ts +16 -1
- package/lib/types/host/ollama/client.d.ts.map +1 -1
- package/lib/types/host/ollama/routes.d.ts +1 -1
- package/lib/types/host/ollama/routes.d.ts.map +1 -1
- package/lib/types/host/ollama/types.d.ts +74 -8
- package/lib/types/host/ollama/types.d.ts.map +1 -1
- package/lib/types/host/step-code/account-pool.d.ts +187 -0
- package/lib/types/host/step-code/account-pool.d.ts.map +1 -0
- package/lib/types/host/step-code/adapter.d.ts +142 -0
- package/lib/types/host/step-code/adapter.d.ts.map +1 -0
- package/lib/types/host/step-code/adopt.d.ts +201 -0
- package/lib/types/host/step-code/adopt.d.ts.map +1 -0
- package/lib/types/host/step-code/cache-stats.d.ts +181 -0
- package/lib/types/host/step-code/cache-stats.d.ts.map +1 -0
- package/lib/types/host/step-code/client.d.ts +331 -0
- package/lib/types/host/step-code/client.d.ts.map +1 -0
- package/lib/types/host/step-code/mapper.d.ts +301 -0
- package/lib/types/host/step-code/mapper.d.ts.map +1 -0
- package/lib/types/host/step-code/model-catalog.d.ts +230 -0
- package/lib/types/host/step-code/model-catalog.d.ts.map +1 -0
- package/lib/types/host/step-code/oauth.d.ts +265 -0
- package/lib/types/host/step-code/oauth.d.ts.map +1 -0
- package/lib/types/host/step-code/routes.d.ts +126 -0
- package/lib/types/host/step-code/routes.d.ts.map +1 -0
- package/lib/types/host/step-code/token-store.d.ts +325 -0
- package/lib/types/host/step-code/token-store.d.ts.map +1 -0
- package/lib/types/host/step-code/types.d.ts +488 -0
- package/lib/types/host/step-code/types.d.ts.map +1 -0
- package/lib/types/host/workbuddy/adapter.d.ts.map +1 -1
- package/lib/types/index.d.ts +5 -1
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/shared/ollama-contracts.d.ts +30 -0
- package/lib/types/shared/ollama-contracts.d.ts.map +1 -1
- package/lib/types/shared/step-code-contracts.d.ts +438 -0
- package/lib/types/shared/step-code-contracts.d.ts.map +1 -0
- package/package.json +1 -1
- package/lib/types/host/glm-coding-plan/signing.d.ts +0 -323
- package/lib/types/host/glm-coding-plan/signing.d.ts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,52 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.23.0 - 2026-10-13
|
|
6
|
+
- **[Ollama] 思考档位从「猜白名单」改为「读模型自己声明的事实」,并接通设置页的默认档位(用户报障:ollama 线路缺少模型思考档位选择器)**
|
|
7
|
+
- **问题(三层各缺一环,不是 UI 漏做)**:本插件其余每条线路都在 `adapter.resolveModel()` 里返回 `reasoning: { efforts, defaultEffort }`,Harness 的模型选择器只在拿到它时才渲染档位下拉——Ollama 是唯一不返回的线路,所以下拉根本不出现。而 Harness 侧的行为不是「静默忽略」而是硬拒绝:`resolveCallWithInfo` 在 `reasoning === undefined` 且调用方传了 `reasoningEffort` 时抛 `UNSUPPORTED_REASONING_EFFORT`。同时设置页的 `defaultReasoningEffort` 是一个**写进去就没人读的死字段**——`token-store.ts` 读写完备,但 `/settings` 路由只处理 `enabled`,卡片没有下拉,`OllamaWebStatus` 里也没有这个字段。
|
|
8
|
+
- **第一处:档位阶梯改为由模型元数据驱动**。`POST /api/show` 返回的顶层 `thinking: { values, default }` 是该模型**唯一一处**自述其 `think` 接受值的来源(官方 thinking.mdx 逐字)。新增 `fetchModelThinking()` 读取它,`reasoningEffortsForModel()` 据此构建阶梯;原有的 `gpt-oss` / `deepseek-r1` / `qwq` / `qwen3` 四个前缀白名单**降级为回退**——只在元数据读不到时使用,无 `declared` 时行为逐字不变。于是白名单之外的家族(如 `glm-4.6:cloud` 若声明 `['low','high']`)也能拿到自己的正确阶梯。
|
|
9
|
+
- **第二处(本轮最关键的缺陷,验收阶段抓出并退回返工)**:档位集合与 wire 取值曾由**两张不同的表**产生——集合走 `reasoningEffortsForModel`,取值走 `thinkForModel`——于是对声明 `values: [true]` 的模型(支持思考、**不允许关闭**),集合仍无条件给出「关闭思考」位置,选中后发出 `reasoning_effort: 'none'`,而官方文档明写 `"none"` 请求 `false`:**等于对一个明确声明不接受 `false` 的模型发了 `false`**。同源漏洞是混合声明 `['low','high',false]` 被判成 `levels` 后 `false` 被字符串分支静默丢弃,该位置**选了什么也不发**。修法不是加特例,而是让正反两向由**同一张表** `{ value, id, name }` 导出:`true` → 开启思考、`false` → 关闭思考、字符串原样保留拼写与声明顺序。`values:[true]` 因此不再提供关闭位,`['low','high',false]` 则三项齐全且各自发出正确的 wire 值。
|
|
10
|
+
- **第三处:接通设置页默认档位**。`OllamaWebStatus` 增加 `defaultReasoningEffort`,`/settings` 与 `/models` 两个分支接受并校验它(只收 `null` 或四档词表,越界返回 400;校验前置到写入之前,避免带多个字段的请求被半应用),客户端新增 `setDefaultReasoningEffort()` 与一个下拉框,`null` 是「不指定」这一可撤销的真实取值而非缺省。
|
|
11
|
+
- **降级纪律**:探测的每一种失败形态(无凭据 / 网络错 / 401 / 500 / 代理 HTML / 结构不符 / 空 values)都返回 `undefined` 且**绝不抛错**——读不到元数据只是「少一个阶梯」,不能让设置页或聊天链路出错。请求侧同理:目标模型表达不出的档位**只丢档位、不丢回合**。探测按 modelId 记忆化(仅成功才缓存,并发合并为一次),且在 `requestStream` 内**惰性**发起——无条件探测会读空 `test/stream-activity-idle.test.ts` 手工喂的心跳流,该用例会变红(此约束写在 `adapter.ts` 注释里)。
|
|
12
|
+
- **验证**:`npm run typecheck` 0 错误;全量 `npm test` 220 passed | 1 skipped(221 文件)、**3670 passed | 7 skipped | 0 failed**。新增 `test/ollama-thinking.test.ts`(24 例,覆盖 `[true]` 无关闭位、两种布尔声明顺序、混合声明三位置各自的 wire 值、8 种探测失败形态、记忆化与并发合并、`:cloud` 后缀命中)与路由/卡片各 7 例。既有 20 例中 19 例一字未改;1 例按新语义重新锚定(`drops an unexpressible stored level...`:原断言 `reasoning_effort === 'auto'`,那正是「把 high 强扭成 true」的旧特例,改为 `toBeUndefined()`——新值更严格,用例主张不变)。
|
|
13
|
+
- **独立验证**:调度者另写一次性用例断言最强不变量——「每一个被提供的档位都能反查回一个声明过的 wire 值」,7/7 通过后删除。
|
|
14
|
+
- **诚实声明**:全部证据来自官方文档与桩测,**没有**对真实 Ollama Cloud 账号实测过各模型的 `/api/show` 返回;「档位会正确出现」是由文档加 444 例桩测推出的结论,不是眼见为实。
|
|
15
|
+
|
|
16
|
+
- **[GLM(ZCode 账号)] 删除客户端签名层(Client Signing V4),并把四条外部证据补进 README 已知限制**
|
|
17
|
+
- **问题**:签名层以「实现了但默认关闭 + 能力门控」的形态长期留在生产路径上——`signing.ts`、契约里的能力位、`DSH_GLM_*` 开关一应俱全,README 也照此写着「默认关、需要显式打开」。它本身是 C 级证据(社区经验 / 架构推断,无实测),按本仓库规则 C 级「不得进入默认路径」;而这一次连一份**能证明自己有用**的证据都没有。
|
|
18
|
+
- **后果**:一个逆向来的签名算法(移植自 MIT 的 `zcode-signer.ts`)留在仓库里、留在能力清单里、留在环境变量表里,此后每一轮改动都要再回答一次「这个开关要不要动」。唯一有实测记录的项目做过 A/B 对照,**带签名与不带签名的响应归一化后完全一致**(都是 429/1113);官方那个本可当作开关信号的 feature gate 端点 `/api/v1/agent/configs` **根本不校验凭据**,两类凭据拿到逐字相同的响应,答不了「签名是否启用」。README 里那句「默认关、需要显式打开」还会让读者以为存在一个可开启的官方机制。
|
|
19
|
+
- **修法**:**整层删除**——生产路径上不再有任何签名接线、能力门控或环境变量入口,能力清单里的对应条目一并去掉。**没被证明的那一半照记不误**:服务端是否真会因为缺签名返回签名错误,至今从未被观察到;这不是「已验证不需要签名」,而是「从未验证过」,两者的区别不因为实现被删掉而消失。
|
|
20
|
+
- **文档**:四条有外部证据的事实补进 README 的「已知限制」,逐字引用并注明来源与证据等级:① 签名层**已删除**及其依据(实测 A/B 归一化一致 + 官方 gate 不校验凭据);② 资源包 / 充值余额与套餐额度**互不消耗**,资源包的入口是通用面 `/api/paas/v4` + 开放平台 API Key,本线路不接(官方配置页 zcode.z.ai/cn/docs/configuration 逐字);③ 免费体验额度的**逐模型构成**(GLM-5.3 300 万 token / 日、GLM-5.3-Flash 500 万 token / 日)与**时限**(仅限 5 天、过期不再补发,官方配置页逐字);④ 本线路**直连** `api.z.ai/api/anthropic`,而官方客户端在 fetch 层把它重写到 `/api/v1/ultra*` 托管网关(官方开源仓库逐字),因此记为观察项而非缺陷。
|
|
21
|
+
- **测试**:删除 `test/glm-coding-plan-signing.test.ts`(原 514 行);不新增用例——被删掉的是一整条能力,生产面随之消失,没有留下需要新覆盖的分支。
|
|
22
|
+
- **验证:`npm run typecheck` 0 错误;全量 `npm test` 219 passed | 1 skipped(220 文件)、3632 passed | 7 skipped | 0 failed。** 改动前基线为 221 passed | 1 skipped(221 文件)、3653 passed | 7 skipped(3660):减少的 21 例与 1 个文件正是被删掉的 `test/glm-coding-plan-signing.test.ts`(21 例 / 514 行),其余用例计数未变。
|
|
23
|
+
|
|
24
|
+
## 0.22.0 - 2026-10-12
|
|
25
|
+
- **[WorkBuddy / 共享号池] 非鉴权的 403 不再误杀整个账号池;「全部账号不可用」不再伪造 429 与 15 分钟冷却(issue #53)**
|
|
26
|
+
- **问题 1(403 一律=凭据失效)**:WorkBuddy 的 `classifyFailure` 只看状态码,`401 || 403` 无条件返回 `INVALID_CREDENTIAL`。代理 / lane 策略 / 同 lane 其它插件合成的应用层拒绝(issue 给出的实测体:`{"error":{"type":"server_error","code":"dsh_compaction_refused","retryable":false}}`)因此被当成 token 失效,账号池把**每一个**账号依次 `markAuthFailed` → `authStatus="expired"`——拒绝属于 lane 而不属于某个账号,所以三个账号无一幸免——此后每个请求在发出前即失败,且**不会自愈**,只有重新登录才能恢复。
|
|
27
|
+
- **修法**:403 改为「正文给出非鉴权的**正面证据**」才改判。判据刻意单向——空正文、网关 HTML、不可解析的 JSON、没有决定性字段的 JSON 一律回落原本的 `INVALID_CREDENTIAL`(fail-closed:读不出的证据绝不能成为「被拒 token 继续留在轮换里」的理由)。能翻案的是**本线路自己不会发出的形状**:字符串 `code`(本线路只说数字码),或 `retryable:false` / `type:"server_error"` 这类明确的「别重试」声明。改判结果是 `PROVIDER_ERROR`,在本线路重试集合之外(同一个请求撞同一条规则,重试只花额度),且**不写账号池**。
|
|
28
|
+
- **问题 2(伪造 429 与 15 分钟)**:共享号池的 `allUnavailableError` 不看「为什么都不可用」,一律返回 `RATE_LIMIT` + `status 429`,文案里的分钟数取自「最短冷却」;当没有任何账号在冷却时 `shortest` 是 `Infinity`,于是落到**硬编码的 `15`**。用户被告知等待一个从未开始、也永远不会结束的窗口,而唯一有效的处置(重新登录)一个字都没提。另外 `retryAfterMs` 把 `Retry-After` 封顶在 10 分钟,所以这条路径上**物理上不可能**出现 15 分钟的真实冷却。
|
|
29
|
+
- **修法**:先问「池里还有没有任何凭据可用的账号」——没有则以 `AUTH` + `status 401` 报「全部 N 个账号均需要重新登录」,不再提冷却;有冷却才按 429 报告,且分钟数在**没有实测重置时刻时是 `null`**(而不是编一个数),`allUnavailableMessage` 钩子签名随之改为 `number | null`,antigravity / glm-coding-plan / step-code 三处覆写同步跟上,并新增可选的 `allAuthFailedMessage` 钩子供线路自定措辞。**刻意排除**「只是这次请求把自己能试的账号试完了」:tried-set 是重试循环的簿记,那些凭据完全可用,不能因此让用户去重新登录。
|
|
30
|
+
- **测试**:号池 3 例(全部凭据失效必须报 AUTH,且文案里不得出现 `429` / `15 分钟`;试完 tried-set 仍报 RATE_LIMIT;钩子拿到的 `waitMinutes` 在没有冷却时不被调用、有真实冷却时是实测分钟数);WorkBuddy 分类器 3 例(401 与裸/不可读 403 保持凭据判定;实测的代理合成 403 必须归 `PROVIDER_ERROR`、落在重试集合外、且文案不劝人重新登录;本线路数字码的 403 仍归凭据)。两处既有断言把旧行为写成了期望(`claude-account-pool` 把「全部账号凭据失效」钉成 `RATE_LIMIT`),按其真实意图(路由拒绝、且不得触发 refresh)改为 `AUTH`。
|
|
31
|
+
- **变异验证**:把 `allUnavailableError` 的 AUTH 分支短路后,4 条用例(含 2 条新增)以真实的 `RATE_LIMIT` / `429` 失败;把 WorkBuddy 的 403 判定短路后,恰好 1 条新增用例以 `INVALID_CREDENTIAL` 失败。恢复后全绿。
|
|
32
|
+
- **验证:`npx tsc -b --force` 0 错误;全量 `npx vitest run` 220 passed | 1 skipped(221 文件)、3653 passed | 7 skipped | 0 failed。**
|
|
33
|
+
- **诚实声明**:403 的正文字段判据来自 issue 给出的实测报文与代码定位,**没有**用一个真实 lane 级 403 复现端到端;断言全部建立在分类器与号池的单元层。
|
|
34
|
+
- **[Step Code] 新增「Step Code(Step Plan 订阅)」线路:StepFun 国区 / 国际区订阅与开放平台 API Key 接入,含套餐额度与缓存用量卡片**
|
|
35
|
+
- **能力来源**:StepFun 官方开源的 Step-Code 客户端。四个凭据 profile(`step_plan` / `step_plan_oversea` / `platform_cn` / `platform_oversea`)**与官方 `STEP_LOGIN_PROFILE_IDS` 逐字相同,一个不多一个不少**;区域(`cn` = stepfun.com,`intl` = stepfun.ai)是**凭据的属性而不是请求的属性**,由 profile 唯一决定,所以设置页不给自由输入——区域交叉的凭据会被上游直接拒绝。同一个号池里可以同时持有两区账号且互不串用。
|
|
36
|
+
- **四条登录入口互不替代**:云端轮询的浏览器授权(**不开本地回调端口**,流程跑在 host 上,卡片每 2 秒轮询)、手工粘贴 Platform API Key、只读导入本机 `~/.stepcode/auth.json`(**只读,绝不改写 stepcode 的任何文件**),以及仅用于读额度的开发者中心凭据。前三条的导入**失败永不阻断**:契约把失败拆成四个 reason(没文件 / 读坏了 / 形状不认识 / 里面不是 Step 的登录态),卡片据此给出四个不同的下一步,一律回落浏览器登录或手工粘贴。
|
|
37
|
+
- **能力不从模型名推断**:模型目录**完全靠运行时发现**,随包表**刻意为空**。每行的一句话描述、是否收图片、接受哪些思考档位、上下文窗口全部来自上游目录字段,拿不到证据时按兜底值显示而不是猜。档位在本地先收敛到**模型真实梯子**(`reasoning_effort_support_list`)再发出去,所以设置里列出 DSH 的完整档位词汇也不会给只认两档的模型发错档。
|
|
38
|
+
- **⚠️ 额度接口是非公开接口,这是本线路唯一的合规与稳定性风险点**:先用开放平台**账号密码**换取 `Oasis-Token`,再用它读 Dashboard。上游随时可以改形状、改鉴权或直接关掉。处置是把它隔离成**一个只读、失败永不阻断**的面:额度读不出来时卡片照旧渲染,模型请求一个字节都不受影响。卡片上如实写出「非公开接口」这行字,不把尽力而为的读数包装成有 SLA 的承诺。
|
|
39
|
+
- **两代套餐分别渲染,不揉成一份「看起来一样」的进度条**:老式账号只有 5 小时 / 周窗口(有已用百分比),新式账号只有 Credit 月池(总额 / 剩余的绝对量)。判定**按载荷形状**(老式窗口字段 vs `credit_buckets`)而不是只信 `plan_family`;两端都认不出来时只显示「认不出」,**一个进度条都不画**——画出来的是上游从没说过存在的东西。折算成百分比同样被拒绝:Credit 桶的分母要自己选,而新式套餐里不同桶的地位并不等价(订阅额度与充值额度不是一回事),折出来的是编的。
|
|
40
|
+
- **缓存区只有 token 维度,不出现任何金额**:Step 服务端是自动前缀缓存,客户端没有「写入」这个动作,所以**写侧恒为 0 并被显式标注**(`always-zero-on-this-route`)而不是画一条永远是 0 的条;官方模型表里四个 cost 键全是 0(单价未文档化),所以整页只展示 token 与命中率,**不展示任何金额**——拿 0 当单价算出「省了 0 元」是正确但无用,拿编的费率算出「省了 N 元」是撒谎。「在请求里发送缓存参数」做成**默认关闭**的能力位,因为官方对 Step 端点默认也不发该字段。
|
|
41
|
+
- **凭据边界**:api_key、`Oasis-Token` 与账号密码**一律不出现在任何 DTO 里**。手工粘贴与账号密码登录的请求体正因如此**刻意不在冻结契约里声明**(它必然带凭据,由 host 侧自行解析);卡片只显示「有没有凭据、从哪来、大概什么时候过期、上次读它出了什么问题」,而这三条秘密只在点击提交那一刻随请求体过一趟 host,随即被清空——不写本地存储、不进 URL、不写日志,也没有任何接口能把它们读回来。
|
|
42
|
+
- **接入方式(全部是追加)**:hub 描述符追加在 `ollama` 之后、输入框胶囊槽位 `step-code-quota` 取 **order 43**(接在 `glm-coding-plan-quota` 的 42 之后顺延)、新增 `dsh-step-code` 命名空间与一张自有样式表。**既有线路的卡片顺序与槽位号一个字符都没有动**——给已上线的线路重排位置没有收益,只有风险。
|
|
43
|
+
- **测试**:新增 `test/step-code-ui.test.tsx`(5 例,jsdom,全程 mock fetch 且**只在本线路 `/step-code/api` 前缀下应答**,越界请求当场抛错)覆盖卡片渲染账号区 / 额度区 / 模型清单、`quota` 为 null 不崩且不画 0%、`windowed` 与 `credit` 两种额度分别渲染、缓存区不出现任何金额且写侧显式声明恒零。既有测试只**追加条目**:`client-registration` 的注入次数、胶囊注册表、`TAB_IDS`、卡片名与开关数;`hub-overview-ui` 的 summary 与卡片顺序;`client-style-ownership` 的 SHEETS 表。
|
|
44
|
+
- **实机验证(本轮用真实账号补齐,分档如实列出)**:
|
|
45
|
+
- **live 验证通过**:浏览器授权开流/轮询;**账号密码换 `Oasis-Token`**(`RegisterDevice` → `SignInByPassword`);用该 token 读 `QueryStepPlanRateLimit` 与 `GetStepPlanStatus`(真实返回套餐 `Plus`、`plan_family=2`、Credit 桶总额与剩余);模型目录字段与档位回落按实测载荷对齐。
|
|
46
|
+
- **仅 mock 验收**:模型面真实对话请求、手工粘贴 Platform API Key 的完整会话、`adopt` 四种失败分支、额度卡片的渲染本身。
|
|
47
|
+
- **上线后修的两处硬伤(都是「HTTP 200/401 却读不出东西」,错误措辞会把根因指向错误的字段)**:
|
|
48
|
+
- **`oasis-appid` 填成了 `oasis-platform` 的值 `web`**,服务端据此查应用配置,直接 `500 app configuration is missing`。正确值是应用 id **`10300`**(响应里 `registry.appId` 会回显,可复核)。该错误当时出现在**两条**路径上(设备注册与额度读取),第一轮只修了前者、漏了后者,导致额度卡片继续报同一个错——**同一常量在多处使用时,修完必须全仓 grep 一遍**。
|
|
49
|
+
- **`SignInByPassword` 的 cookie 里没带匿名 token**,服务端找不到登录会话,一律 `401 token is missing` / `token is illegal`。实测对照:cookie 带 **`access...refresh` 无空格成对形式**→ 200 并返回 token;只带 access 或只带 refresh → 401;两段之间**多一个空格** → `token is malformed: could not base64 decode header`。这三个 401 的措辞各不相同却同因,代码注释已记录完整对照表。
|
|
50
|
+
|
|
5
51
|
## 0.21.0 - 2026-10-12
|
|
6
52
|
- **[Ollama] 修复添加 Key 后「订阅服务」整页空白;补齐线路启停开关;「全不选」与勾选状态实时同步到模型选择器**
|
|
7
53
|
- **问题 1(整页空白)**:`/ollama/api/accounts` 的 `add` 分支独自返回 `{ id }`,其余动作都返回完整 status。客户端把动作回包直接当作渲染状态,`status.models` 为 `undefined` 时渲染期 `TypeError` 把设置页整棵 React 子树打崩。修法:add 与其他动作一样回落到统一的完整 status 应答;客户端渲染路径对残缺 status 一律降级为空区块(`status?.models ?? []`),任何残缺载荷永不再崩页。
|
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
- [WorkBuddy 线路](#workbuddy-线路)
|
|
17
17
|
- [Claude(订阅)线路](#claude订阅线路)
|
|
18
18
|
- [GLM(ZCode 账号)线路](#glmzcode-账号线路)
|
|
19
|
+
- [Step Code(Step Plan 订阅)线路](#step-codestep-plan-订阅线路)
|
|
19
20
|
- [子代理模型授权](#子代理模型授权0215-起032-起强制指定模型)
|
|
20
21
|
- [随包分发的 Agent Preset](#随包分发的-agent-preset)
|
|
21
22
|
- [本机登录](#本机登录)
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
|
|
27
28
|
## 线路总览
|
|
28
29
|
|
|
29
|
-
本插件同时接入 **
|
|
30
|
+
本插件同时接入 **9 条订阅线路**,每条各自独立注册 Provider、独立登录、独立额度卡片。
|
|
30
31
|
|
|
31
32
|
| Provider ID | 订阅 | 协议 | 登录方式 | 模型目录来源 |
|
|
32
33
|
| --- | --- | --- | --- | --- |
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
| `minimax-code` | MiniMax Code 编程订阅 | Anthropic Messages | **复用桌面端登录态** 或设备码 | **硬编码**(见下) |
|
|
39
40
|
| `antigravity` | Google Antigravity | Gemini | Google OAuth | 内置表 |
|
|
40
41
|
| `glm-coding-plan` | GLM Coding Plan(ZCode 账号,国区 BigModel / 国际区 Z.ai) | Anthropic Messages + OpenAI Chat Completions(按模型声明) | ZCode 账号 OAuth(浏览器中转轮询)+ 可选导入本机 ZCode 登录态 | 随包目录(源自官方 `zcode-builtin.json`) |
|
|
42
|
+
| `step-code` | StepFun Step Plan 订阅(国区 api.stepfun.com / 国际区 api.stepfun.ai)或开放平台 API Key | OpenAI Chat Completions | **云端轮询**浏览器授权(不开本地回调端口)/ 手工粘贴 Platform API Key / 只读导入本机 `~/.stepcode/auth.json` | **实时运行时发现**(随包表刻意为空) |
|
|
41
43
|
|
|
42
44
|
> **只有 minimax-code 是硬编码目录,而且是有意的**:该端点的 `GET /v1/models` **未对订阅流量开放**(返回 503 `direct_route_not_configured`),任何「实时目录」都只会是一个必然失败的请求。其取值转录自本机官方客户端的 `config.yaml`。
|
|
43
45
|
>
|
|
@@ -858,9 +860,60 @@ access token / refresh token / 授权码 / PKCE verifier**;诊断里提到某
|
|
|
858
860
|
确切错误码与重置节奏;
|
|
859
861
|
- 「闲时任务」类免费算力(welcome 页所述)本线路**未接入**,它属于另一条调度路径。
|
|
860
862
|
- **上游没有 refresh_token 交换接口。** 官方客户端对刷新直接抛「OAuth 暂未提供 refresh token 交换接口,请重新登录」。因此 `access_token` 过期**只能重新登录**;插件能自动重取的只有业务 JWT 这一层(提前 120 秒 + 0~60 秒抖动防尖峰),而且**它只服务国际区**。账号行上的「重新登录」在 host 这一侧只做两件事:撤掉鉴权失败标记与冷却,让这一行重新参与轮转;真正的登录要由卡片再开一次流程。
|
|
861
|
-
- **客户端签名层(Client Signing V4
|
|
863
|
+
- **客户端签名层(Client Signing V4)已从本线路删除——不是默认关闭,也没有可显式打开的开关。** 生产路径上不再有任何签名接线、能力门控或环境变量入口,一个逆向来的签名算法连同它自己那份故障面一起被移除。删它的理由是它**从未有过能支撑上线的证据**:唯一有实测记录的项目做过 A/B 对照,**带签名与不带签名的响应归一化后完全一致**(都是 429/1113),从未观察到服务端因为缺签名而拒绝请求;而官方那个本可当作开关信号的 feature gate 端点 `/api/v1/agent/configs` **根本不校验凭据**——两类凭据拿到逐字相同的响应,所以它答不了「签名是否启用」,拿它当证据等于把一份不区分凭据的响应读成了区分。留下这条限制是为了同时记着**没被证明的那一半**:服务端是否真会因为缺签名返回签名错误,**至今从未被观察到**——这不是「已验证不需要签名」,而是「从未验证过」,两者的区别不因为实现被删掉而消失。
|
|
864
|
+
- **资源包 / 充值余额与套餐额度互不消耗,本线路两边都碰不到用户充的钱。** 官方文档 zcode.z.ai/cn/docs/configuration 把资源包写成**与 Coding Plan 并列的另一个入口**:一节标题就是『资源包 / 充值余额』,正文『使用开放平台模型资源包或充值余额等通用 API 场景,填写 OpenAI 接口地址即可』,给的地址是通用面 `https://open.bigmodel.cn/api/paas/v4`(国际区 `https://api.z.ai/api/paas/v4`)。同一页逐字:『Anthropic 接口不适用于资源包 / 余额场景:只有从未购买过 Coding Plan 的账号,走 Anthropic 接口时才会消耗余额;只要买过套餐(无论是否用完、是否到期),该接口都不会走余额,需要额外加白处理』;『Coding 端点仅限 Coding 场景,与通用端点不可互相替代,也不会互相消耗额度』。因此本线路的模型面(Anthropic)与套餐面在结构上就不触及资源包:**资源包的入口是上面那个通用面,凭据是开放平台的 API Key**——官方在这一节的措辞是「API Key 模式」,与「编程套餐」授权绑定账号的**非 API Key 模式**相对,**不是本线路换出来的那把 Coding Plan Key,本线路根本不接这类 Key**。用户在这条线路上**不会**误烧充值余额;要确实用资源包,请走 DSH 自带的「自定义模型 API」,那是另一个面、另一把 Key。
|
|
865
|
+
- **免费体验额度的逐模型构成与时限(只补上一条已有条目没写的两项,不重复它)。** 上一条只写了体验额度存在,没写它由哪几个模型、各多少、什么时候失效。官方配置页(逐字:zcode.z.ai/cn/docs/configuration):『每日体验额度由两类模型额度组成…… GLM-5.3 300 万 token / 日;GLM-5.3-Flash 500 万 token / 日』;『注意:体验额度仅限 5 天。每日额度只在这 5 天内发放,体验期结束后即失效,并非长期每天都有』。两者相加正好是那句「每天 800 万 token」——但**这是两个模型各自的份额,不是所有 GLM 模型共享的一口池子**,也只有 GLM-5.3 / GLM-5.3-Flash 沾得到;体验期一过额度**不再补发**,卡片上「免费体验额度」那一档不能读成长期权益。**仍未验证(拿到账号后请先复验)**:这两个日额度用尽后服务端返回的确切业务码、以及每日重置发生在什么钟点,仍没有实机样本。
|
|
866
|
+
- **与官方路径的形态差异:本线路直连 `api.z.ai/api/anthropic`,官方客户端却在 fetch 层把同一个 URL 重写到托管网关。** 官方开源仓库 `zai-org/ZCode` 的 `apps/zcode-cli/packages/adapters/src/model/official-coding-plan-gateway.ts` 里,`GATEWAY_PATH_BY_ENDPOINT` 把 `'https://api.z.ai:443/api/anthropic/v1/messages'` 映射到 `'/api/v1/ultra-zai/anthropic/v1/messages'`、把 `'https://open.bigmodel.cn:443/api/anthropic/v1/messages'` 映射到 `'/api/v1/ultra/anthropic/v1/messages'`。也就是说官方那一侧**不打这个基址**,而是在 fetch 层改写到 `/api/v1/ultra*` 网关前缀下;本线路照抄的是前一个形状。这记为**观察项而不是缺陷**:两个独立的第三方实现直连该基址都成功过(能拿到 1113 业务码恰恰说明认证这一关已经过了),而网关前缀是官方托管面自己的编排,本线路不复刻它、也不需要它。**仍未验证**:托管网关是否会在某些请求特征上施加通用面没有的额外策略。
|
|
862
867
|
- **国区兑换链未验证。** 证据来自三个社区实现(等级 B,逆向实测而非官方契约),三者**都以国际区为主**,国区业务面的形状是否同构没有实测样本。国区兑换失败会带上明确说明与下一步建议(改用国际区,或用 `DSH_GLM_CN_BUSINESS_HOST` 等环境变量指向实测过的部署),**不静默失败**。同理,国区配额到底打 `bigmodel.cn` 还是官方文档里那句「亦可用 `open.bigmodel.cn`」也没有实测,本插件取 `bigmodel.cn`。
|
|
863
|
-
- **兑换链的所有端点都可用 `DSH_GLM_*` 环境变量覆盖**(两区的业务 host、模型面 host、授权入口、appId / client_id、Key 名、OAuth
|
|
868
|
+
- **兑换链的所有端点都可用 `DSH_GLM_*` 环境变量覆盖**(两区的业务 host、模型面 host、授权入口、appId / client_id、Key 名、OAuth 控制面基址)。这是为等级 B 的兑换链准备的退路:上游一次变更让整条链失效时,回滚是改一个环境变量,而不是发一个版本。
|
|
869
|
+
|
|
870
|
+
## Step Code(Step Plan 订阅)线路
|
|
871
|
+
|
|
872
|
+
`step-code`(显示名 **Step Code(Step Plan 订阅)**)接入 **StepFun 的 Step Plan 订阅**(国区 `api.stepfun.com` / 国际区 `api.stepfun.ai`)以及开放平台 API Key。国区与国际区是**两套互不通用**的部署:`api.stepfun.ai` 的凭据打国区端点会被上游直接拒绝。因此**区域是凭据的属性而不是请求的属性**,它由凭据里的 `profile` 唯一决定,号池里可以同时持有两区账号且互不串用。
|
|
873
|
+
|
|
874
|
+
> ⚠️ **额度接口是非公开接口,这是本线路唯一的合规与稳定性风险点。** 用量与配额读的不是公开 API:先用开放平台**账号密码**换取一个 `Oasis-Token`,再用它读 Dashboard(见下)。上游随时可以改它的形状、改它的鉴权方式或直接关掉它。本插件的处置是把它彻底隔离成**一个只读、失败永不阻断**的面——额度读不出来时卡片照旧渲染、模型请求一个字节都不受影响。反过来说,**不要把额度数字当成有 SLA 的承诺**:它是尽力而为的读数,不是账单。而且它需要你额外交出一次开放平台账号密码,这件事本身就是把订阅账号的登录权交给了另一条链路。
|
|
875
|
+
|
|
876
|
+
**登录**(四条路,任选其一,互不替代):
|
|
877
|
+
|
|
878
|
+
1. **云端轮询的浏览器授权**(订阅账号):本线路**不开本地回调端口**,流程跑在 host 上,你在浏览器里人工确认,卡片每 2 秒轮询一次进度。授权页地址始终显示在卡片上——即使 host 打开浏览器失败,你也能自己复制打开;
|
|
879
|
+
2. **手工粘贴 Platform API Key**(对应两个 `platform_*` 凭据类型,按量计费):没有浏览器、或不想走授权时用它。这条兜底通道**常驻在页面上**(收起态只是一个开关),因为它是浏览器打不开时唯一能完成登录的地方;
|
|
880
|
+
3. **只读导入本机 `stepcode` 登录态**(可选):读 `~/.stepcode/auth.json`(**只读**,从不创建、修改或删除 stepcode 的任何文件)。四种失败各有各的下一步(没文件 / 读坏了 / 形状不认识 / 里面不是 Step 的登录态),**失败永不阻断**,一律回落上面两条路;
|
|
881
|
+
4. **额度凭据**(与上面三条都独立):开放平台账号密码或手工粘贴的 `Oasis-Token`,**只**用于读额度,不参与模型请求。密码与 Token 只在你点击提交的那一刻随请求体交给 host:不写入本地存储、不进 URL、不写日志,也**没有任何接口能把它们读回来**。
|
|
882
|
+
|
|
883
|
+
**能力**:OpenAI Chat Completions;模型目录**完全靠运行时发现**,随包表**刻意为空**。卡片上每行模型的一句话描述、是否收图片、接受哪些思考档位、上下文窗口,全部来自上游目录字段,**拿不到证据时按兜底值显示而不是猜**(本线路明确禁止从模型名推断能力)。档位在本地先收敛到**模型真实梯子**(`reasoning_effort_support_list`)上再发出去,所以设置里列出 DSH 的完整档位词汇也不会给只认两档的模型发错档。区域交叉的凭据会被上游拒绝,所以卡片不给自由输入——四个 profile 取值与官方逐字相同。
|
|
884
|
+
|
|
885
|
+
**缓存**:Step 服务端是**自动前缀缓存**(前缀够了就命中),客户端既没有缓存参数也没有「写入」这个动作。因此本线路:(1) **只展示读侧一个维度**(读入 token、未命中输入、命中率、样本请求数);(2) **写侧恒为 0 并被显式标注**(`always-zero-on-this-route`),不画一条永远是 0 的进度条——把线路事实渲染成故障比不画更糟;(3) **整页不出现任何金额**:官方模型表里四个 cost 键全是 0(单价未文档化),拿 0 当单价算出「省了 0 元」是正确但无用,拿编的费率算出「省了 N 元」是撒谎。(4) 「在请求里发送缓存参数」是一个**默认关闭**的能力位,因为它会让请求带上 Step 文档里没有说明过的字段(官方对 Step 端点也是不发的)。
|
|
886
|
+
|
|
887
|
+
**已知限制**:
|
|
888
|
+
|
|
889
|
+
- **实机验证到什么程度(如实分档,不打包成一句「已验证」)**:
|
|
890
|
+
- **已用真实账号 live 验证**:① 云端轮询浏览器授权开流与轮询;② **开放平台账号密码换取 `Oasis-Token`**(`RegisterDevice` → `SignInByPassword`);③ 用该 token 读 **`QueryStepPlanRateLimit` 与 `GetStepPlanStatus`**(返回真实套餐 `Plus`、`plan_family=2`、Credit 桶总额与剩余);④ 模型目录字段与档位回落按实测载荷对齐。
|
|
891
|
+
- **仅 mock 验收**:模型面的真实对话请求、手工粘贴 Platform API Key 走通完整会话、`adopt` 的四种失败分支、以及额度卡片在真实载荷下的渲染(形状取自实测响应,但渲染本身是单测覆盖)。
|
|
892
|
+
- 因此这一节不是免责套话:**列出的分档就是上线时的实际置信度**,读的人可以据此判断哪一块需要自己再试一次;
|
|
893
|
+
- **额度读的是非公开的开发者中心接口**(见开头的风险提示)。两代套餐同时在用(老式 5 小时 / 周窗口,与 Credit 月池),判定**按载荷形状**(老式窗口字段 vs `credit_buckets`)而不是只信 `plan_family`;两端都认不出来时只显示「认不出」,**一个进度条都不画**;
|
|
894
|
+
- **没有 refresh_token 交换链**。access token 过期只能重新走登录;账号行上的「重新登录」在 host 侧只解除鉴权失败标记与冷却,真正重登要由卡片再开一次流程;
|
|
895
|
+
- **上下文窗口的输出上限是推导值**。端点不报输出上限,所以默认等于上下文窗口——这是一个诚实的兜底,不是一份上游声明;
|
|
896
|
+
- **品牌标记取自官方站点资产**,不是本地画的占位图形:形状逐字转录 `platform.stepfun.com/favicon.svg`,底砖色用该文件里的 `#1d1d1d`。抓取日期与字节数记在 `brand-icons.tsx` 的注释里,便于日后核对;
|
|
897
|
+
|
|
898
|
+
### 插件路由(Step Code)
|
|
899
|
+
所有路由都以 `/step-code/api` 为前缀:
|
|
900
|
+
|
|
901
|
+
| 方法 | 路径 | 说明 |
|
|
902
|
+
| --- | --- | --- |
|
|
903
|
+
| GET | `/status` | 凭据类型与区域、号池、模型目录、额度快照、缓存统计与登录流程;页面唯一的读口 |
|
|
904
|
+
| POST | `/settings` | 启用开关、勾选模型、上下文窗口覆盖、默认思考档位、手选账号、缓存参数能力位 |
|
|
905
|
+
| POST | `/accounts` | 号池动作:`set-primary` / `clear-cooldown` / `delete` / `relogin` / `strategy` |
|
|
906
|
+
| POST | `/login/start` | 按 profile 开一次云端轮询登录流,立即返回流程状态(不阻塞、不开本地回调端口) |
|
|
907
|
+
| GET | `/login/status` | 轮询登录流程状态;**只有这一条 GET 会推进状态机**,关掉设置页之后就不会继续打上游 |
|
|
908
|
+
| POST | `/login/cancel` | 取消登录流程 |
|
|
909
|
+
| POST | `/login/manual` | 手工粘贴 Platform API Key(**请求体必然带凭据,刻意不在冻结契约里声明**) |
|
|
910
|
+
| POST | `/adopt` | 只读导入本机 stepcode 登录态;失败**永不阻断**,每种失败都是契约里的一个 reason,卡片据此回落 |
|
|
911
|
+
| POST | `/connection/test` | 沿模型面做一次探测(**裸 DTO,不走信封**);它答「这个账号能不能发请求」,答不了「这个具体模型会不会成功」 |
|
|
912
|
+
| POST | `/quota` | 强制刷新额度;一次失败的额度读不是一次失败的请求,卡片照旧渲染 |
|
|
913
|
+
| POST | `/catalog/refresh` | 强制刷新模型目录 |
|
|
914
|
+
| POST | `/quota/credential` | `mode: 'password' | 'manual' | 'clear'`。**非公开的开发者中心接口**;凭据只在提交时的请求体里过一趟,永远不回读 |
|
|
915
|
+
|
|
916
|
+
与其它线路一样,所有修改状态的路由只接受同源 JSON POST 并校验 `Origin` 与 `Host`。**响应里永远不含 api_key、`Oasis-Token` 或账号密码的原文**——下发的只有「有没有凭据、从哪来、大概什么时候过期、上次读它出了什么问题」。
|
|
864
917
|
|
|
865
918
|
## 本机登录
|
|
866
919
|
|