@eddyskywalker/dsh-chatgpt-subscription 0.20.0 → 0.22.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 +36 -0
- package/README.md +51 -1
- package/lib/client.js +2674 -528
- package/lib/client.js.map +1 -1
- package/lib/index.js +7712 -2590
- package/lib/types/client/glm-coding-plan/GlmCodingPlanSection.d.ts.map +1 -1
- package/lib/types/client/glm-coding-plan/locales.d.ts +11 -17
- 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 +2 -2
- package/lib/types/client/ollama/api.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/ollama/adapter.d.ts.map +1 -1
- package/lib/types/host/ollama/routes.d.ts.map +1 -1
- package/lib/types/host/ollama/token-store.d.ts +8 -3
- package/lib/types/host/ollama/token-store.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 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/shared/ollama-contracts.d.ts +8 -1
- 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/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.22.0 - 2026-10-12
|
|
6
|
+
- **[WorkBuddy / 共享号池] 非鉴权的 403 不再误杀整个账号池;「全部账号不可用」不再伪造 429 与 15 分钟冷却(issue #53)**
|
|
7
|
+
- **问题 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 而不属于某个账号,所以三个账号无一幸免——此后每个请求在发出前即失败,且**不会自愈**,只有重新登录才能恢复。
|
|
8
|
+
- **修法**:403 改为「正文给出非鉴权的**正面证据**」才改判。判据刻意单向——空正文、网关 HTML、不可解析的 JSON、没有决定性字段的 JSON 一律回落原本的 `INVALID_CREDENTIAL`(fail-closed:读不出的证据绝不能成为「被拒 token 继续留在轮换里」的理由)。能翻案的是**本线路自己不会发出的形状**:字符串 `code`(本线路只说数字码),或 `retryable:false` / `type:"server_error"` 这类明确的「别重试」声明。改判结果是 `PROVIDER_ERROR`,在本线路重试集合之外(同一个请求撞同一条规则,重试只花额度),且**不写账号池**。
|
|
9
|
+
- **问题 2(伪造 429 与 15 分钟)**:共享号池的 `allUnavailableError` 不看「为什么都不可用」,一律返回 `RATE_LIMIT` + `status 429`,文案里的分钟数取自「最短冷却」;当没有任何账号在冷却时 `shortest` 是 `Infinity`,于是落到**硬编码的 `15`**。用户被告知等待一个从未开始、也永远不会结束的窗口,而唯一有效的处置(重新登录)一个字都没提。另外 `retryAfterMs` 把 `Retry-After` 封顶在 10 分钟,所以这条路径上**物理上不可能**出现 15 分钟的真实冷却。
|
|
10
|
+
- **修法**:先问「池里还有没有任何凭据可用的账号」——没有则以 `AUTH` + `status 401` 报「全部 N 个账号均需要重新登录」,不再提冷却;有冷却才按 429 报告,且分钟数在**没有实测重置时刻时是 `null`**(而不是编一个数),`allUnavailableMessage` 钩子签名随之改为 `number | null`,antigravity / glm-coding-plan / step-code 三处覆写同步跟上,并新增可选的 `allAuthFailedMessage` 钩子供线路自定措辞。**刻意排除**「只是这次请求把自己能试的账号试完了」:tried-set 是重试循环的簿记,那些凭据完全可用,不能因此让用户去重新登录。
|
|
11
|
+
- **测试**:号池 3 例(全部凭据失效必须报 AUTH,且文案里不得出现 `429` / `15 分钟`;试完 tried-set 仍报 RATE_LIMIT;钩子拿到的 `waitMinutes` 在没有冷却时不被调用、有真实冷却时是实测分钟数);WorkBuddy 分类器 3 例(401 与裸/不可读 403 保持凭据判定;实测的代理合成 403 必须归 `PROVIDER_ERROR`、落在重试集合外、且文案不劝人重新登录;本线路数字码的 403 仍归凭据)。两处既有断言把旧行为写成了期望(`claude-account-pool` 把「全部账号凭据失效」钉成 `RATE_LIMIT`),按其真实意图(路由拒绝、且不得触发 refresh)改为 `AUTH`。
|
|
12
|
+
- **变异验证**:把 `allUnavailableError` 的 AUTH 分支短路后,4 条用例(含 2 条新增)以真实的 `RATE_LIMIT` / `429` 失败;把 WorkBuddy 的 403 判定短路后,恰好 1 条新增用例以 `INVALID_CREDENTIAL` 失败。恢复后全绿。
|
|
13
|
+
- **验证:`npx tsc -b --force` 0 错误;全量 `npx vitest run` 220 passed | 1 skipped(221 文件)、3653 passed | 7 skipped | 0 failed。**
|
|
14
|
+
- **诚实声明**:403 的正文字段判据来自 issue 给出的实测报文与代码定位,**没有**用一个真实 lane 级 403 复现端到端;断言全部建立在分类器与号池的单元层。
|
|
15
|
+
- **[Step Code] 新增「Step Code(Step Plan 订阅)」线路:StepFun 国区 / 国际区订阅与开放平台 API Key 接入,含套餐额度与缓存用量卡片**
|
|
16
|
+
- **能力来源**:StepFun 官方开源的 Step-Code 客户端。四个凭据 profile(`step_plan` / `step_plan_oversea` / `platform_cn` / `platform_oversea`)**与官方 `STEP_LOGIN_PROFILE_IDS` 逐字相同,一个不多一个不少**;区域(`cn` = stepfun.com,`intl` = stepfun.ai)是**凭据的属性而不是请求的属性**,由 profile 唯一决定,所以设置页不给自由输入——区域交叉的凭据会被上游直接拒绝。同一个号池里可以同时持有两区账号且互不串用。
|
|
17
|
+
- **四条登录入口互不替代**:云端轮询的浏览器授权(**不开本地回调端口**,流程跑在 host 上,卡片每 2 秒轮询)、手工粘贴 Platform API Key、只读导入本机 `~/.stepcode/auth.json`(**只读,绝不改写 stepcode 的任何文件**),以及仅用于读额度的开发者中心凭据。前三条的导入**失败永不阻断**:契约把失败拆成四个 reason(没文件 / 读坏了 / 形状不认识 / 里面不是 Step 的登录态),卡片据此给出四个不同的下一步,一律回落浏览器登录或手工粘贴。
|
|
18
|
+
- **能力不从模型名推断**:模型目录**完全靠运行时发现**,随包表**刻意为空**。每行的一句话描述、是否收图片、接受哪些思考档位、上下文窗口全部来自上游目录字段,拿不到证据时按兜底值显示而不是猜。档位在本地先收敛到**模型真实梯子**(`reasoning_effort_support_list`)再发出去,所以设置里列出 DSH 的完整档位词汇也不会给只认两档的模型发错档。
|
|
19
|
+
- **⚠️ 额度接口是非公开接口,这是本线路唯一的合规与稳定性风险点**:先用开放平台**账号密码**换取 `Oasis-Token`,再用它读 Dashboard。上游随时可以改形状、改鉴权或直接关掉。处置是把它隔离成**一个只读、失败永不阻断**的面:额度读不出来时卡片照旧渲染,模型请求一个字节都不受影响。卡片上如实写出「非公开接口」这行字,不把尽力而为的读数包装成有 SLA 的承诺。
|
|
20
|
+
- **两代套餐分别渲染,不揉成一份「看起来一样」的进度条**:老式账号只有 5 小时 / 周窗口(有已用百分比),新式账号只有 Credit 月池(总额 / 剩余的绝对量)。判定**按载荷形状**(老式窗口字段 vs `credit_buckets`)而不是只信 `plan_family`;两端都认不出来时只显示「认不出」,**一个进度条都不画**——画出来的是上游从没说过存在的东西。折算成百分比同样被拒绝:Credit 桶的分母要自己选,而新式套餐里不同桶的地位并不等价(订阅额度与充值额度不是一回事),折出来的是编的。
|
|
21
|
+
- **缓存区只有 token 维度,不出现任何金额**:Step 服务端是自动前缀缓存,客户端没有「写入」这个动作,所以**写侧恒为 0 并被显式标注**(`always-zero-on-this-route`)而不是画一条永远是 0 的条;官方模型表里四个 cost 键全是 0(单价未文档化),所以整页只展示 token 与命中率,**不展示任何金额**——拿 0 当单价算出「省了 0 元」是正确但无用,拿编的费率算出「省了 N 元」是撒谎。「在请求里发送缓存参数」做成**默认关闭**的能力位,因为官方对 Step 端点默认也不发该字段。
|
|
22
|
+
- **凭据边界**:api_key、`Oasis-Token` 与账号密码**一律不出现在任何 DTO 里**。手工粘贴与账号密码登录的请求体正因如此**刻意不在冻结契约里声明**(它必然带凭据,由 host 侧自行解析);卡片只显示「有没有凭据、从哪来、大概什么时候过期、上次读它出了什么问题」,而这三条秘密只在点击提交那一刻随请求体过一趟 host,随即被清空——不写本地存储、不进 URL、不写日志,也没有任何接口能把它们读回来。
|
|
23
|
+
- **接入方式(全部是追加)**:hub 描述符追加在 `ollama` 之后、输入框胶囊槽位 `step-code-quota` 取 **order 43**(接在 `glm-coding-plan-quota` 的 42 之后顺延)、新增 `dsh-step-code` 命名空间与一张自有样式表。**既有线路的卡片顺序与槽位号一个字符都没有动**——给已上线的线路重排位置没有收益,只有风险。
|
|
24
|
+
- **测试**:新增 `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 表。
|
|
25
|
+
- **实机验证(本轮用真实账号补齐,分档如实列出)**:
|
|
26
|
+
- **live 验证通过**:浏览器授权开流/轮询;**账号密码换 `Oasis-Token`**(`RegisterDevice` → `SignInByPassword`);用该 token 读 `QueryStepPlanRateLimit` 与 `GetStepPlanStatus`(真实返回套餐 `Plus`、`plan_family=2`、Credit 桶总额与剩余);模型目录字段与档位回落按实测载荷对齐。
|
|
27
|
+
- **仅 mock 验收**:模型面真实对话请求、手工粘贴 Platform API Key 的完整会话、`adopt` 四种失败分支、额度卡片的渲染本身。
|
|
28
|
+
- **上线后修的两处硬伤(都是「HTTP 200/401 却读不出东西」,错误措辞会把根因指向错误的字段)**:
|
|
29
|
+
- **`oasis-appid` 填成了 `oasis-platform` 的值 `web`**,服务端据此查应用配置,直接 `500 app configuration is missing`。正确值是应用 id **`10300`**(响应里 `registry.appId` 会回显,可复核)。该错误当时出现在**两条**路径上(设备注册与额度读取),第一轮只修了前者、漏了后者,导致额度卡片继续报同一个错——**同一常量在多处使用时,修完必须全仓 grep 一遍**。
|
|
30
|
+
- **`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 的措辞各不相同却同因,代码注释已记录完整对照表。
|
|
31
|
+
|
|
32
|
+
## 0.21.0 - 2026-10-12
|
|
33
|
+
- **[Ollama] 修复添加 Key 后「订阅服务」整页空白;补齐线路启停开关;「全不选」与勾选状态实时同步到模型选择器**
|
|
34
|
+
- **问题 1(整页空白)**:`/ollama/api/accounts` 的 `add` 分支独自返回 `{ id }`,其余动作都返回完整 status。客户端把动作回包直接当作渲染状态,`status.models` 为 `undefined` 时渲染期 `TypeError` 把设置页整棵 React 子树打崩。修法:add 与其他动作一样回落到统一的完整 status 应答;客户端渲染路径对残缺 status 一律降级为空区块(`status?.models ?? []`),任何残缺载荷永不再崩页。
|
|
35
|
+
- **问题 2(缺开关)**:总览卡片里 Ollama 是唯一没有启停开关的线路(`canToggle: false` 硬编码)。适配器其实早已读取 `enabled` 旗标,缺的只是接线:新增 `POST /ollama/api/settings { enabled }`(与其余线路同形同义),hub 描述符接上开关,总览聚合回报真实旗标而非恒 `true`。
|
|
36
|
+
- **问题 3(「全不选」弹回全选)**:`enabledModelIds` 的「空数组 = 不过滤」语义使「全不选」写入 `[]` 后被读回成全选,长清单永远无法收窄。改为三态:`null` = 不过滤(全部,含日后新同步的模型)、数组 = 显式选择(`[]` = 全不选)。设置文件写入 `version: 2` 标记;旧文件的空数组只能解释为「未动过的默认」,读回 `null`,存量用户行为不变。手动勾满整张清单时客户端归一化回 `null`,「全部」继续跟随目录而非冻结在凑巧完整的那一刻。
|
|
37
|
+
- **问题 4(取消勾选后选择器仍显示)**:Ollama 是唯一不在设置变更后发 `llm/adapters-updated` 的线路,模型选择器只能等别的线路碰巧发事件才刷新。`/models` 与 `/settings` 的实际写入现在都发该事件,与其余线路逐字对齐。
|
|
38
|
+
- **测试**:路由层 8 例新增(add/delete 应答必须是完整 status、全不选持久化为 `[]`、`null` 恢复不过滤、version-2 前后文件各自读法、开关往返、只读不发事件);适配器层按三态改写 3 例;客户端层 3 例(残缺动作回包不崩页、全不选后全部不勾且计数 0/2、勾满归一化为 `null`)。反向验证:撤掉客户端加固后「残缺回包」用例以原样 `TypeError: Cannot read properties of undefined (reading 'length')` 失败,恢复后全绿。
|
|
39
|
+
- **验证:`npm run typecheck` 0 错误;全量 `npm test` 215 passed | 1 skipped(216 文件)、3494 passed | 7 skipped | 0 failed。**
|
|
40
|
+
|
|
5
41
|
## 0.20.0 - 2026-10-12
|
|
6
42
|
- **[MiniMax Code] 新增「限额重置卡」:查看可用卡与近 30 天流水,选卡确认后重置套餐限额**
|
|
7
43
|
- **能力来源**:MiniMax 官方桌面端 v3.1.1(2026-10-04)起提供「限额重置」——订阅用户可在用量页查看可用重置卡与近 30 天获得/使用记录,**选择一张卡并确认后**重置对应限额。本插件复刻它,接同一组上游接口。
|
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
|
>
|
|
@@ -862,6 +864,54 @@ access token / refresh token / 授权码 / PKCE verifier**;诊断里提到某
|
|
|
862
864
|
- **国区兑换链未验证。** 证据来自三个社区实现(等级 B,逆向实测而非官方契约),三者**都以国际区为主**,国区业务面的形状是否同构没有实测样本。国区兑换失败会带上明确说明与下一步建议(改用国际区,或用 `DSH_GLM_CN_BUSINESS_HOST` 等环境变量指向实测过的部署),**不静默失败**。同理,国区配额到底打 `bigmodel.cn` 还是官方文档里那句「亦可用 `open.bigmodel.cn`」也没有实测,本插件取 `bigmodel.cn`。
|
|
863
865
|
- **兑换链的所有端点都可用 `DSH_GLM_*` 环境变量覆盖**(两区的业务 host、模型面 host、授权入口、appId / client_id、Key 名、OAuth 控制面基址,签名层开关也在其中)。这是为等级 B 的兑换链准备的退路:上游一次变更让整条链失效时,回滚是改一个环境变量,而不是发一个版本。
|
|
864
866
|
|
|
867
|
+
## Step Code(Step Plan 订阅)线路
|
|
868
|
+
|
|
869
|
+
`step-code`(显示名 **Step Code(Step Plan 订阅)**)接入 **StepFun 的 Step Plan 订阅**(国区 `api.stepfun.com` / 国际区 `api.stepfun.ai`)以及开放平台 API Key。国区与国际区是**两套互不通用**的部署:`api.stepfun.ai` 的凭据打国区端点会被上游直接拒绝。因此**区域是凭据的属性而不是请求的属性**,它由凭据里的 `profile` 唯一决定,号池里可以同时持有两区账号且互不串用。
|
|
870
|
+
|
|
871
|
+
> ⚠️ **额度接口是非公开接口,这是本线路唯一的合规与稳定性风险点。** 用量与配额读的不是公开 API:先用开放平台**账号密码**换取一个 `Oasis-Token`,再用它读 Dashboard(见下)。上游随时可以改它的形状、改它的鉴权方式或直接关掉它。本插件的处置是把它彻底隔离成**一个只读、失败永不阻断**的面——额度读不出来时卡片照旧渲染、模型请求一个字节都不受影响。反过来说,**不要把额度数字当成有 SLA 的承诺**:它是尽力而为的读数,不是账单。而且它需要你额外交出一次开放平台账号密码,这件事本身就是把订阅账号的登录权交给了另一条链路。
|
|
872
|
+
|
|
873
|
+
**登录**(四条路,任选其一,互不替代):
|
|
874
|
+
|
|
875
|
+
1. **云端轮询的浏览器授权**(订阅账号):本线路**不开本地回调端口**,流程跑在 host 上,你在浏览器里人工确认,卡片每 2 秒轮询一次进度。授权页地址始终显示在卡片上——即使 host 打开浏览器失败,你也能自己复制打开;
|
|
876
|
+
2. **手工粘贴 Platform API Key**(对应两个 `platform_*` 凭据类型,按量计费):没有浏览器、或不想走授权时用它。这条兜底通道**常驻在页面上**(收起态只是一个开关),因为它是浏览器打不开时唯一能完成登录的地方;
|
|
877
|
+
3. **只读导入本机 `stepcode` 登录态**(可选):读 `~/.stepcode/auth.json`(**只读**,从不创建、修改或删除 stepcode 的任何文件)。四种失败各有各的下一步(没文件 / 读坏了 / 形状不认识 / 里面不是 Step 的登录态),**失败永不阻断**,一律回落上面两条路;
|
|
878
|
+
4. **额度凭据**(与上面三条都独立):开放平台账号密码或手工粘贴的 `Oasis-Token`,**只**用于读额度,不参与模型请求。密码与 Token 只在你点击提交的那一刻随请求体交给 host:不写入本地存储、不进 URL、不写日志,也**没有任何接口能把它们读回来**。
|
|
879
|
+
|
|
880
|
+
**能力**:OpenAI Chat Completions;模型目录**完全靠运行时发现**,随包表**刻意为空**。卡片上每行模型的一句话描述、是否收图片、接受哪些思考档位、上下文窗口,全部来自上游目录字段,**拿不到证据时按兜底值显示而不是猜**(本线路明确禁止从模型名推断能力)。档位在本地先收敛到**模型真实梯子**(`reasoning_effort_support_list`)上再发出去,所以设置里列出 DSH 的完整档位词汇也不会给只认两档的模型发错档。区域交叉的凭据会被上游拒绝,所以卡片不给自由输入——四个 profile 取值与官方逐字相同。
|
|
881
|
+
|
|
882
|
+
**缓存**:Step 服务端是**自动前缀缓存**(前缀够了就命中),客户端既没有缓存参数也没有「写入」这个动作。因此本线路:(1) **只展示读侧一个维度**(读入 token、未命中输入、命中率、样本请求数);(2) **写侧恒为 0 并被显式标注**(`always-zero-on-this-route`),不画一条永远是 0 的进度条——把线路事实渲染成故障比不画更糟;(3) **整页不出现任何金额**:官方模型表里四个 cost 键全是 0(单价未文档化),拿 0 当单价算出「省了 0 元」是正确但无用,拿编的费率算出「省了 N 元」是撒谎。(4) 「在请求里发送缓存参数」是一个**默认关闭**的能力位,因为它会让请求带上 Step 文档里没有说明过的字段(官方对 Step 端点也是不发的)。
|
|
883
|
+
|
|
884
|
+
**已知限制**:
|
|
885
|
+
|
|
886
|
+
- **实机验证到什么程度(如实分档,不打包成一句「已验证」)**:
|
|
887
|
+
- **已用真实账号 live 验证**:① 云端轮询浏览器授权开流与轮询;② **开放平台账号密码换取 `Oasis-Token`**(`RegisterDevice` → `SignInByPassword`);③ 用该 token 读 **`QueryStepPlanRateLimit` 与 `GetStepPlanStatus`**(返回真实套餐 `Plus`、`plan_family=2`、Credit 桶总额与剩余);④ 模型目录字段与档位回落按实测载荷对齐。
|
|
888
|
+
- **仅 mock 验收**:模型面的真实对话请求、手工粘贴 Platform API Key 走通完整会话、`adopt` 的四种失败分支、以及额度卡片在真实载荷下的渲染(形状取自实测响应,但渲染本身是单测覆盖)。
|
|
889
|
+
- 因此这一节不是免责套话:**列出的分档就是上线时的实际置信度**,读的人可以据此判断哪一块需要自己再试一次;
|
|
890
|
+
- **额度读的是非公开的开发者中心接口**(见开头的风险提示)。两代套餐同时在用(老式 5 小时 / 周窗口,与 Credit 月池),判定**按载荷形状**(老式窗口字段 vs `credit_buckets`)而不是只信 `plan_family`;两端都认不出来时只显示「认不出」,**一个进度条都不画**;
|
|
891
|
+
- **没有 refresh_token 交换链**。access token 过期只能重新走登录;账号行上的「重新登录」在 host 侧只解除鉴权失败标记与冷却,真正重登要由卡片再开一次流程;
|
|
892
|
+
- **上下文窗口的输出上限是推导值**。端点不报输出上限,所以默认等于上下文窗口——这是一个诚实的兜底,不是一份上游声明;
|
|
893
|
+
- **品牌标记取自官方站点资产**,不是本地画的占位图形:形状逐字转录 `platform.stepfun.com/favicon.svg`,底砖色用该文件里的 `#1d1d1d`。抓取日期与字节数记在 `brand-icons.tsx` 的注释里,便于日后核对;
|
|
894
|
+
|
|
895
|
+
### 插件路由(Step Code)
|
|
896
|
+
所有路由都以 `/step-code/api` 为前缀:
|
|
897
|
+
|
|
898
|
+
| 方法 | 路径 | 说明 |
|
|
899
|
+
| --- | --- | --- |
|
|
900
|
+
| GET | `/status` | 凭据类型与区域、号池、模型目录、额度快照、缓存统计与登录流程;页面唯一的读口 |
|
|
901
|
+
| POST | `/settings` | 启用开关、勾选模型、上下文窗口覆盖、默认思考档位、手选账号、缓存参数能力位 |
|
|
902
|
+
| POST | `/accounts` | 号池动作:`set-primary` / `clear-cooldown` / `delete` / `relogin` / `strategy` |
|
|
903
|
+
| POST | `/login/start` | 按 profile 开一次云端轮询登录流,立即返回流程状态(不阻塞、不开本地回调端口) |
|
|
904
|
+
| GET | `/login/status` | 轮询登录流程状态;**只有这一条 GET 会推进状态机**,关掉设置页之后就不会继续打上游 |
|
|
905
|
+
| POST | `/login/cancel` | 取消登录流程 |
|
|
906
|
+
| POST | `/login/manual` | 手工粘贴 Platform API Key(**请求体必然带凭据,刻意不在冻结契约里声明**) |
|
|
907
|
+
| POST | `/adopt` | 只读导入本机 stepcode 登录态;失败**永不阻断**,每种失败都是契约里的一个 reason,卡片据此回落 |
|
|
908
|
+
| POST | `/connection/test` | 沿模型面做一次探测(**裸 DTO,不走信封**);它答「这个账号能不能发请求」,答不了「这个具体模型会不会成功」 |
|
|
909
|
+
| POST | `/quota` | 强制刷新额度;一次失败的额度读不是一次失败的请求,卡片照旧渲染 |
|
|
910
|
+
| POST | `/catalog/refresh` | 强制刷新模型目录 |
|
|
911
|
+
| POST | `/quota/credential` | `mode: 'password' | 'manual' | 'clear'`。**非公开的开发者中心接口**;凭据只在提交时的请求体里过一趟,永远不回读 |
|
|
912
|
+
|
|
913
|
+
与其它线路一样,所有修改状态的路由只接受同源 JSON POST 并校验 `Origin` 与 `Host`。**响应里永远不含 api_key、`Oasis-Token` 或账号密码的原文**——下发的只有「有没有凭据、从哪来、大概什么时候过期、上次读它出了什么问题」。
|
|
914
|
+
|
|
865
915
|
## 本机登录
|
|
866
916
|
|
|
867
917
|
**每条线路只在自己的详情页里回答关于本机的问题**。ChatGPT(Codex)线路的 ChatGPT 卡片里,「登录」按钮**旁边**就是「导入本机 Codex CLI 登录」——与 Claude 页面上那个收编按钮同样的位置、同样的次要样式;点它可以省掉再走一次 ChatGPT 授权。Claude Code 与 MiniMax Code 各自的设置页里本来就各有一个导入入口,不在这里重复。
|