@eddyskywalker/dsh-chatgpt-subscription 0.21.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 +27 -0
- package/README.md +51 -1
- package/lib/client.js +2661 -516
- package/lib/client.js.map +1 -1
- package/lib/index.js +7657 -2573
- 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/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/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/step-code-contracts.d.ts +438 -0
- package/lib/types/shared/step-code-contracts.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step Code(Step Plan 订阅)线路的模型目录:URL 归一化、目录解析、能力装配。
|
|
3
|
+
*
|
|
4
|
+
* 存在的原因是本线路的一条硬规则,与 glm 线路那条同源而结论相反:
|
|
5
|
+
* **能力不得从模型名推断,而目录完全靠运行时发现**。
|
|
6
|
+
*
|
|
7
|
+
* ## 随包目录为什么是空的
|
|
8
|
+
*
|
|
9
|
+
* 官方 Step-Code 的随包目录字面量就是空的,注释写得很直白(`step-provider/index.ts:148-152`):
|
|
10
|
+
*
|
|
11
|
+
* > No built-in baseline: the Step catalog is discovered entirely from `{base}/v1/models`
|
|
12
|
+
* > after login. When discovery is unavailable (offline / logged out / request failure)
|
|
13
|
+
* > the list stays empty.
|
|
14
|
+
*
|
|
15
|
+
* 所以这里**不造**一张随包模型表。没有证据的 model id 进目录,等于让用户在没读过任何
|
|
16
|
+
* 声明的情况下就用上一个未知能力的模型;把一个未知能力的模型渲染成「未声明模型」行
|
|
17
|
+
* (见 {@link undeclaredStepCodeModelEntry})至少是诚实的。
|
|
18
|
+
*
|
|
19
|
+
* 真正保证「取不到目录时选择器不为空」的,是 {@link undeclaredStepCodeModelEntry}:
|
|
20
|
+
* 上游给什么 id 就以未声明行进入目录,不猜窗口、不认图、不发档位。
|
|
21
|
+
*
|
|
22
|
+
* ## 本文件与官方实现的对应
|
|
23
|
+
*
|
|
24
|
+
* 本文件把官方那几段**分散**在 `step-provider/index.ts` 里的东西收在一起
|
|
25
|
+
* (归一化、发现、逐模型装配),并把它们暴露成后面几个波次可以直接 import 的函数:
|
|
26
|
+
*
|
|
27
|
+
* - {@link normalizeStepCodeApiBaseUrl} ← `normalizeStepApiBaseUrl`(`index.ts:378-401`)
|
|
28
|
+
* - {@link stepCodeOpenAiBaseUrl} ← `stepOpenAiBaseUrl`(`index.ts:411`)
|
|
29
|
+
* - {@link stepCodeModelsDetailBaseUrl} ← `stepModelsDetailBaseUrl`(`index.ts:420`)
|
|
30
|
+
* - {@link parseStepCodeModelListing} ← `fetchStepModels` 的解析与过滤部分
|
|
31
|
+
* - {@link undeclaredStepCodeModelEntry} ← `stepModelConfig` 的全部字段缺省路径
|
|
32
|
+
*/
|
|
33
|
+
import type { StepCodeModelOption, StepCodeProfile, StepCodeReasoningEffort } from '../../shared/step-code-contracts.ts';
|
|
34
|
+
/**
|
|
35
|
+
* 把一个 Step 端点归一化到「路由前缀」。
|
|
36
|
+
*
|
|
37
|
+
* Step 的配置(以及旧版 models.json)接受三种写法:带版本的操作 URL(`/v1/messages`)、
|
|
38
|
+
* `/messages` 操作、以及 `/v1` 父路径。把这些尾部段循环剥掉,调用方才能在同一个值上
|
|
39
|
+
* 按当前方言补上正确的后缀而不把版本段发两次。
|
|
40
|
+
*
|
|
41
|
+
* **幂等**是官方的明确要求(`index.ts:382-387`):某个中间版本产出的文件里可能已经
|
|
42
|
+
* 有一个重复的后缀(`/v1/v1/messages`),而这个函数也被用来修这样的存量文件。
|
|
43
|
+
* 所以它不是「剥一层」而是「循环剥到剥不动」,对任意多个残留的版本 / 操作段都收敛。
|
|
44
|
+
*
|
|
45
|
+
* 解析不了的输入原样返回:修复 models.json 里一个畸形的自定义条目时,
|
|
46
|
+
* 那个条目必须保持原样,好让正常的校验去报它的问题,而不是在这里被静默改写。
|
|
47
|
+
*
|
|
48
|
+
* @param value - 任意一个 Step 模型面端点写法。
|
|
49
|
+
* @returns 去掉尾部版本 / 操作段之后的路由前缀。
|
|
50
|
+
*/
|
|
51
|
+
export declare function normalizeStepCodeApiBaseUrl(value: string): string;
|
|
52
|
+
/**
|
|
53
|
+
* OpenAI 风格的 base(`.../v1`),供 chat 与目录发现共用。
|
|
54
|
+
*
|
|
55
|
+
* `apiBase` 传进来时通常已经归一化过(尾部 `/v1` 已剥),所以补一个 `/v1`
|
|
56
|
+
* 对四条 profile 都对:
|
|
57
|
+
*
|
|
58
|
+
* - `step_plan` → `https://api.stepfun.com/step_plan/v1`
|
|
59
|
+
* - `platform_cn` → `https://api.stepfun.com/v1`
|
|
60
|
+
*
|
|
61
|
+
* chat 请求在这个 base 上拼 `/chat/completions`,目录发现拼 `/models`。
|
|
62
|
+
* 这里再归一化一次是**有意的**:调用方可能直接传了环境变量里的原始值。
|
|
63
|
+
*/
|
|
64
|
+
export declare function stepCodeOpenAiBaseUrl(apiBase: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* 逐模型详情查询的 base:**域名根的 `/v1`**。
|
|
67
|
+
*
|
|
68
|
+
* 这一处的端点位置是反直觉的:profile 是 `step_plan` 时目录在 `.../step_plan/v1/models`,
|
|
69
|
+
* 但详情在 `https://api.stepfun.com/v1/models/{id}`——带子路径的那个变体会 404
|
|
70
|
+
* (逐字:`index.ts:414-419`)。所以这里取 `origin` 而不是路径。
|
|
71
|
+
*
|
|
72
|
+
* 不是合法 URL 时原样返回(与归一化函数同样的理由:让它保持可校验)。
|
|
73
|
+
*/
|
|
74
|
+
export declare function stepCodeModelsDetailBaseUrl(apiBase: string): string;
|
|
75
|
+
/** chat completions 的完整 URL(OpenAI 兼容面,全部四条 profile 走这一条)。 */
|
|
76
|
+
export declare function stepCodeChatCompletionsUrl(apiBase: string): string;
|
|
77
|
+
/** 模型列表的完整 URL。 */
|
|
78
|
+
export declare function stepCodeModelsUrl(apiBase: string): string;
|
|
79
|
+
/** 一行模型能力。与 `StepCodeModelOption` 同义,去掉的只是「用户设置」那一半(见 {@link catalogModelOptions})。 */
|
|
80
|
+
export interface StepCodeModelEntry {
|
|
81
|
+
id: string;
|
|
82
|
+
name: string;
|
|
83
|
+
/** 一句话能力描述:思考形态 / 可选档位 / 输入模态 / 上下文窗口。由 {@link describeStepCodeModel} 生成。 */
|
|
84
|
+
hint: string;
|
|
85
|
+
/** 服务该模型线的 profile。同一个 id 在四条 profile 上的可用性可能不同。 */
|
|
86
|
+
profiles: readonly StepCodeProfile[];
|
|
87
|
+
/**
|
|
88
|
+
* 该模型**真实**接受的思考档位梯子(mapper 会把它当 ladder 传给收敛函数)。
|
|
89
|
+
*
|
|
90
|
+
* **空数组是有意语义**:该模型完全不发思考控制字段
|
|
91
|
+
* (`convergeStepCodeEffort` 对空梯子返回 null,mapper 据此不发出 `reasoning_effort`)。
|
|
92
|
+
* 这不是「忘了填」,是「不发」。
|
|
93
|
+
*/
|
|
94
|
+
reasoningEfforts: readonly StepCodeReasoningEffort[];
|
|
95
|
+
/** 思考能否关闭。与上一条**正交**:档位非空而本项为 false = 恒定开启。 */
|
|
96
|
+
thinkingDisableable: boolean;
|
|
97
|
+
/** 是否接受 image 输入。 */
|
|
98
|
+
supportsImages: boolean;
|
|
99
|
+
/** 目录报的 `max_input_tokens`,也就是上下文窗口。 */
|
|
100
|
+
defaultContextWindow: number;
|
|
101
|
+
/** 调用方不指定输出上限时本线路请求的输出上限;端点不报,默认等于上下文窗口。 */
|
|
102
|
+
defaultMaxTokens: number;
|
|
103
|
+
/** 官方描述;没有逐字来源时为 null(不编文案)。 */
|
|
104
|
+
description: string | null;
|
|
105
|
+
}
|
|
106
|
+
/** 一行能力去掉 `hint` 的样子:hint 由 {@link withHint} 从其余字段生成,不手写。 */
|
|
107
|
+
export type StepCodeModelFacts = Omit<StepCodeModelEntry, 'hint'>;
|
|
108
|
+
/**
|
|
109
|
+
* 解析上游 `GET {base}/v1/models` 的应答。
|
|
110
|
+
*
|
|
111
|
+
* 接受 `{ data: [...] }`(OpenAI 形状)与裸数组两种形状:两个都要认,是因为
|
|
112
|
+
* 「目录空掉」与「目录里多了奇怪的条目」同样难排查,而多认一种形状的代价是零。
|
|
113
|
+
*
|
|
114
|
+
* 无 id 的条目被丢弃而不是给一个占位 id:一个没有 id 的模型行在选择器里无法被请求,
|
|
115
|
+
* 留着只是让用户点一个必然失败的东西。
|
|
116
|
+
*
|
|
117
|
+
* @param payload - 上游应答解析后的 JSON。
|
|
118
|
+
* @returns 能力行,顺序与上游一致;解析不出任何东西时是空数组。
|
|
119
|
+
*/
|
|
120
|
+
export declare function parseStepCodeModelListing(payload: unknown): StepCodeModelEntry[];
|
|
121
|
+
/**
|
|
122
|
+
* 随包发布的目录:**空**。
|
|
123
|
+
*
|
|
124
|
+
* 理由与取值见文件头:官方就没有随包基线(`STEP_MODELS = []`,`index.ts:154`),
|
|
125
|
+
* 本线路也不编一张。它在代码里仍然作为常量导出,是为了让「随包目录存在且为空」
|
|
126
|
+
* 这件事本身是一个可以被断言的事实,而不是「忘了写这个文件」。
|
|
127
|
+
*
|
|
128
|
+
* 留空**不会**让选择器变空:取不到目录时目录由 {@link undeclaredStepCodeModelEntry}
|
|
129
|
+
* 的未声明行撑住(上游给什么 id 就以什么 id 出现),而两者都没有时线路只是不暴露模型。
|
|
130
|
+
*/
|
|
131
|
+
export declare const STEP_CODE_MODEL_CATALOG: readonly StepCodeModelEntry[];
|
|
132
|
+
/** 随包目录里的全部 id(恒为空数组;保留导出形状是为了让调用方的类型推导稳定)。 */
|
|
133
|
+
export declare const STEP_CODE_MODEL_IDS: readonly string[];
|
|
134
|
+
/**
|
|
135
|
+
* 首次安装默认勾选的模型。
|
|
136
|
+
*
|
|
137
|
+
* 恒为空:因为随包目录是空的(见上),而真实目录在登录后才由运行时发现。
|
|
138
|
+
* token-store 把它作为默认值的唯一来源——默认值取自**随包**目录而不是运行时目录,
|
|
139
|
+
* 是为了让「用户没选过」与「用户选了运行时目录里的某个 id」这两件事不互相污染
|
|
140
|
+
* (同 glm 线路把 `GLM_MODEL_CATALOG` 排除在设置文档之外的同一条理由)。
|
|
141
|
+
*/
|
|
142
|
+
export declare const DEFAULT_VISIBLE_MODEL_IDS: readonly string[];
|
|
143
|
+
/**
|
|
144
|
+
* 未知模型的**未声明**行。
|
|
145
|
+
*
|
|
146
|
+
* 什么时候会有:上游目录里出现了本线路没有逐字能力的 id(发了新模型,或本仓库还没跟上)。
|
|
147
|
+
* 这时最诚实的做法是什么都不主张:
|
|
148
|
+
*
|
|
149
|
+
* - `reasoningEfforts: []` → `convergeStepCodeEffort` 返回 null,mapper 一个字段都不发;
|
|
150
|
+
* - `supportsImages: false` → 请求里的图片按「读不出来」明说,而不是发一个上游会拒的 image_url;
|
|
151
|
+
* - `thinkingDisableable: true` → 目录没声明「恒定开启」,那就永远不发关闭值;
|
|
152
|
+
* - 上下文窗口只有在上游明确报了 `max_input_tokens` 时才用它的值,否则用兜底值。
|
|
153
|
+
*
|
|
154
|
+
* 但本线路**不**因此把 id 藏起来:这是与 glm 线路不同的一处决定。
|
|
155
|
+
* 那里未声明行默认不勾选,是因为那行的 `wire` 是 `null`——调它必然拿到 1212;
|
|
156
|
+
* 这里的协议面是固定的(四条 profile 全是 OpenAI Chat Completions),调它是合法的,
|
|
157
|
+
* 只是能力未知。所以未声明行**默认可见**,只是文案点明它是未声明的。
|
|
158
|
+
*/
|
|
159
|
+
export declare function undeclaredStepCodeModelEntry(id: string, options?: {
|
|
160
|
+
contextWindow?: number;
|
|
161
|
+
profiles?: readonly StepCodeProfile[];
|
|
162
|
+
}): StepCodeModelEntry;
|
|
163
|
+
/**
|
|
164
|
+
* 查一行模型能力;给定目录里没有时返回**未声明行**而不是 undefined。
|
|
165
|
+
*
|
|
166
|
+
* 返回未声明行而不是空,是为了让调用方只需要处理一种东西:每个 id 都有一份
|
|
167
|
+
* 「不主张什么」的声明,不必另开一条「找不到模型」的分支。
|
|
168
|
+
*/
|
|
169
|
+
export declare function resolveStepCodeModel(id: string, catalog?: readonly StepCodeModelEntry[]): StepCodeModelEntry;
|
|
170
|
+
/** 该模型真实接受的思考档位;不在目录里时是空数组(即「不发任何思考控制字段」)。 */
|
|
171
|
+
export declare function stepCodeReasoningEfforts(id: string, catalog?: readonly StepCodeModelEntry[]): readonly StepCodeReasoningEffort[];
|
|
172
|
+
/** 该模型是否接受图片输入;不在目录里时为 false(不认图比乱认图安全)。 */
|
|
173
|
+
export declare function stepCodeModelSupportsImages(id: string, catalog?: readonly StepCodeModelEntry[]): boolean;
|
|
174
|
+
/** 该模型的输出上限;不在目录里时取「等于上下文窗口」。 */
|
|
175
|
+
export declare function maxOutputTokensFor(id: string, catalog?: readonly StepCodeModelEntry[]): number;
|
|
176
|
+
/** 该模型的上下文窗口;不在目录里时取 {@link DEFAULT_CONTEXT_WINDOW}。 */
|
|
177
|
+
export declare function defaultContextWindowFor(id: string, catalog?: readonly StepCodeModelEntry[]): number;
|
|
178
|
+
/** 目录里的全部 id。 */
|
|
179
|
+
export declare function listModelIds(catalog?: readonly StepCodeModelEntry[]): string[];
|
|
180
|
+
/** 目录条目数,供 hub 概览显示「M 个模型可用」。 */
|
|
181
|
+
export declare function catalogSize(catalog?: readonly StepCodeModelEntry[]): number;
|
|
182
|
+
/**
|
|
183
|
+
* {@link catalogSize} 的别名。
|
|
184
|
+
*
|
|
185
|
+
* 存在的唯一理由是名字歧义:本线路的「随包目录」恒为空,所以下游看到 `catalog` 时
|
|
186
|
+
* 需要能一眼分清它指随包表还是运行时发现的表(运行时表要传进来,随包表不用)。
|
|
187
|
+
* 两个名字指向同一个函数,不是两份逻辑。
|
|
188
|
+
*/
|
|
189
|
+
export declare const catalogTotal: typeof catalogSize;
|
|
190
|
+
/** 一条 profile 能调的模型(`profiles` 是路由事实:不在列表里的不要发过去)。 */
|
|
191
|
+
export declare function modelsForProfile(profile: StepCodeProfile, catalog?: readonly StepCodeModelEntry[]): StepCodeModelEntry[];
|
|
192
|
+
/**
|
|
193
|
+
* 从一行能力生成设置卡上的一句话描述(四个要素:思考形态 / 档位 / 输入模态 / 上下文窗口)。
|
|
194
|
+
*
|
|
195
|
+
* 由数据生成而不是逐行手写,是为了让文案**不可能与能力表漂移**:手写文案出过
|
|
196
|
+
* 「三个档位」的模型实际只有两档这种事故,而这几个字段都要被 mapper 当成事实使用。
|
|
197
|
+
*
|
|
198
|
+
* @param entry - 能力行。
|
|
199
|
+
* @param prefix - 可选前缀(未声明行用「未声明模型」点明这不是已核实的声明)。
|
|
200
|
+
*/
|
|
201
|
+
export declare function describeStepCodeModel(entry: StepCodeModelEntry, prefix?: string): string;
|
|
202
|
+
/** 用户设置对目录装配的两处覆盖。 */
|
|
203
|
+
export interface StepCodeCatalogOptionOverrides {
|
|
204
|
+
/**
|
|
205
|
+
* 用户勾选的模型 id。
|
|
206
|
+
*
|
|
207
|
+
* **缺省或空数组 = 不过滤(全选)**;非空 = 显式选择(含只有一项)。
|
|
208
|
+
*
|
|
209
|
+
* 为什么是这两条而不是三态(`null` = 不过滤):冻结契约里的
|
|
210
|
+
* `StepCodeSettingsUpdateDto.enabledModelIds` 是 `string[]`,没有 null 这一格;
|
|
211
|
+
* 而本线路的目录是**登录后才运行时发现**的,一个刚装上还没登录的用户手里
|
|
212
|
+
* 必然只有一个空数组。把空数组读成「一个都不启用」会让设置页在用户还没登录时
|
|
213
|
+
* 就显示成「已禁用全部模型」——那是关于目录的谎报,目录这时根本还不存在。
|
|
214
|
+
* 真要把模型全关,关线路总开关(`enabled`)是明确且语义正确的那一个动作。
|
|
215
|
+
*/
|
|
216
|
+
enabledModelIds?: readonly string[];
|
|
217
|
+
/** 逐模型上下文窗口覆盖;null / 非正数表示用目录默认值。 */
|
|
218
|
+
contextWindowOverrides?: Readonly<Record<string, number | null | undefined>>;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* 把目录装配成设置面的模型行。
|
|
222
|
+
*
|
|
223
|
+
* `hint` 在这里生成(而不是写死在表里),所以「文案与能力表一致」是结构保证的:
|
|
224
|
+
* 表里改一次档位或图片支持,卡片上的那句话就跟着变。
|
|
225
|
+
*
|
|
226
|
+
* 未声明行**默认可见**(与 glm 线路相反,理由见 {@link undeclaredStepCodeModelEntry}):
|
|
227
|
+
* 本线路的协议面是固定的,调用它是合法的,未知的只是能力。
|
|
228
|
+
*/
|
|
229
|
+
export declare function catalogModelOptions(catalog?: readonly StepCodeModelEntry[], overrides?: StepCodeCatalogOptionOverrides): StepCodeModelOption[];
|
|
230
|
+
//# sourceMappingURL=model-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-catalog.d.ts","sourceRoot":"","sources":["../../../../src/host/step-code/model-catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 云端轮询式浏览器登录(**不开本地回调端口**)。
|
|
3
|
+
*
|
|
4
|
+
* 逐字照抄官方三件套:`login-client.ts`(init/poll 的协议与重试)、
|
|
5
|
+
* `login-polling.ts`(轮询循环与截止)、`step-provider/index.ts:268-309`(登录整体)。
|
|
6
|
+
* 状态机外壳照抄 `workbuddy/oauth.ts`(flow / controller / getWebLoginStatus / resetWebLogin),
|
|
7
|
+
* 因为设置卡片跟随的是同一组四个入口。
|
|
8
|
+
*
|
|
9
|
+
* ---------------------------------------------------------------------------
|
|
10
|
+
* 两个值,两种角色,**绝不可混用**(逐字 login-client.ts:11-16)
|
|
11
|
+
* ---------------------------------------------------------------------------
|
|
12
|
+
*
|
|
13
|
+
* - `poll_token` —— 客户端侧唯一的凭据。它**只**出现在 `Authorization: Bearer` 头里,
|
|
14
|
+
* 绝不进 URL、日志或磁盘。
|
|
15
|
+
* - `flow_id` —— 公开标识,会进浏览器地址栏、历史与截图,单独一个兑不出凭据。
|
|
16
|
+
*
|
|
17
|
+
* 本文件把这件事做成结构性的:poll_token 只作为 `pollToken` 参数流向 `request()` 的
|
|
18
|
+
* 头构造那一处(见 `loginHeaders`),URL 由 authBase + 路径 + flow_id 拼成,
|
|
19
|
+
* 两段代码互不相交;uid 与 flow_id 的过滤也各有自己的上限(UID_MAX_LENGTH / FLOW_ID_PATTERN)。
|
|
20
|
+
*
|
|
21
|
+
* ---------------------------------------------------------------------------
|
|
22
|
+
* 这条线路的凭据永不过期、永不刷新
|
|
23
|
+
* ---------------------------------------------------------------------------
|
|
24
|
+
* Step 的 api_key 不是会话令牌(index.ts:363-371),所以:
|
|
25
|
+
*
|
|
26
|
+
* - 凭据形态固定为 {type:'oauth', access, refresh: STATIC_REFRESH_TOKEN, expires: STATIC_EXPIRES_AT};
|
|
27
|
+
* - `refreshStepCodeCredential` 存在,但**永远抛错**——它存在的意义是让任何「刷新」路径
|
|
28
|
+
* 得到一句明确的拒绝,而不是悄悄拿哨兵去换一次必然失败的新凭据。
|
|
29
|
+
*/
|
|
30
|
+
import type { StepCodeLoginFlowStatus, StepCodeProfile } from '../../shared/step-code-contracts.ts';
|
|
31
|
+
/**
|
|
32
|
+
* 开流请求体里的终端信息(逐字 `StepCliClientInfo`,index.ts:280-285)。
|
|
33
|
+
*
|
|
34
|
+
* **只用于上游审计**,从不参与鉴权:`name` 固定是官方的 'stepcode',因为服务端
|
|
35
|
+
* 按它识别这条协议;本插件的身份由 `version` 字段如实上报,不冒充官方版本。
|
|
36
|
+
*/
|
|
37
|
+
export interface StepCodeClientInfo {
|
|
38
|
+
readonly name: string;
|
|
39
|
+
readonly version: string;
|
|
40
|
+
readonly platform: string;
|
|
41
|
+
}
|
|
42
|
+
/** 客户端名逐字照抄官方(`defaultStepCliClientInfo`,login-client.ts:104-108)。 */
|
|
43
|
+
export declare const STEP_CODE_CLIENT_NAME = "stepcode";
|
|
44
|
+
/**
|
|
45
|
+
* 接入层没有给版本时上报的版本串。
|
|
46
|
+
*
|
|
47
|
+
* 如实取一个「未知」而不是编一个像真的版本号:上游把它写进审计日志,编造会让
|
|
48
|
+
* 排障时看到一条不存在的客户端版本。接入层(有 `package.json` 的那一层)应传真实版本。
|
|
49
|
+
*/
|
|
50
|
+
export declare const STEP_CODE_CLIENT_VERSION_UNKNOWN = "0.0.0-unknown";
|
|
51
|
+
/** 审计信息(逐字 login-client.ts:104-108:平台取 process.platform-process.arch)。 */
|
|
52
|
+
export declare function defaultStepCodeClientInfo(version: string): StepCodeClientInfo;
|
|
53
|
+
/**
|
|
54
|
+
* 新的一次登录用的 poll_token:`randomBytes(32).toString('hex')`(逐字 index.ts:278)。
|
|
55
|
+
*
|
|
56
|
+
* 32 字节 = 64 位十六进制,与 `POLL_TOKEN_PATTERN` 对齐。它只进 Authorization 头。
|
|
57
|
+
*/
|
|
58
|
+
export declare function createStepCodePollToken(): string;
|
|
59
|
+
/**
|
|
60
|
+
* 一次登录请求失败的类别(逐字 `StepCliLoginErrorKind`,login-client.ts:70-76)。
|
|
61
|
+
*
|
|
62
|
+
* - `http`:非 2xx,或 2xx 但信封里的 `status` 非 0。
|
|
63
|
+
* - `protocol`:2xx 但形状或字段值不合协议(**永不重试**)。
|
|
64
|
+
* - `transport`:请求根本没拿到响应。
|
|
65
|
+
*/
|
|
66
|
+
export type StepCodeLoginErrorKind = 'http' | 'protocol' | 'transport';
|
|
67
|
+
/** 一条登录请求错误;`httpStatus` 只在 http 类里有意义。 */
|
|
68
|
+
export declare class StepCodeLoginRequestError extends Error {
|
|
69
|
+
readonly kind: StepCodeLoginErrorKind;
|
|
70
|
+
readonly httpStatus?: number;
|
|
71
|
+
constructor(kind: StepCodeLoginErrorKind, message: string, options?: {
|
|
72
|
+
readonly httpStatus?: number;
|
|
73
|
+
readonly cause?: unknown;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 这条错误值不值得自动重试(逐字 `isRetryableStepCliLoginError`,login-client.ts:95-100)。
|
|
78
|
+
*
|
|
79
|
+
* protocol 永不重试(形状不对说明对面不是我们以为的那个服务端);transport 重试;
|
|
80
|
+
* http 只在 408 / 429 / >=500 时重试。
|
|
81
|
+
*/
|
|
82
|
+
export declare function isRetryableStepCodeLoginError(error: unknown): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* 一次登录请求的响应体上限:64 KiB(逐字 login-client.ts:32)。
|
|
85
|
+
*
|
|
86
|
+
* 两个响应都是小 JSON;不设上限时,一个坏掉或恶意的端点可以把内存吃光。
|
|
87
|
+
*/
|
|
88
|
+
export declare const STEP_CODE_MAX_RESPONSE_BYTES: number;
|
|
89
|
+
/** 开流成功后的三件事(逐字 StepCliLoginInit,login-client.ts:49-57)。 */
|
|
90
|
+
export interface StepCodeLoginInit {
|
|
91
|
+
/** 公开标识:会进浏览器地址栏,单独一个兑不出凭据。 */
|
|
92
|
+
readonly flowId: string;
|
|
93
|
+
/** 永远由客户端自己拼;服务端可能返回的 authorize_url 被**忽略**(见下)。 */
|
|
94
|
+
readonly authorizeUrl: string;
|
|
95
|
+
/** 已 clamp 到 <= 60。 */
|
|
96
|
+
readonly pollIntervalSec: number;
|
|
97
|
+
/** 上游硬截止,Unix **秒**。 */
|
|
98
|
+
readonly expiresAt: number;
|
|
99
|
+
}
|
|
100
|
+
export interface StepCodeCliLoginInitInput {
|
|
101
|
+
readonly profile: StepCodeProfile;
|
|
102
|
+
readonly pollToken: string;
|
|
103
|
+
readonly client: StepCodeClientInfo;
|
|
104
|
+
readonly fetchFn?: typeof fetch;
|
|
105
|
+
readonly signal?: AbortSignal;
|
|
106
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* POST {authBase}/api/stdhttp/v1/cli-login/init。
|
|
110
|
+
*
|
|
111
|
+
* 请求体(逐字 index.ts:126-135):profile、**origin**(授权中心的源站,不是模型面)、
|
|
112
|
+
* client 审计信息。
|
|
113
|
+
*
|
|
114
|
+
* 授权页 URL **客户端自己拼**(逐字 login-client.ts:139-141):服务端可能返回
|
|
115
|
+
* authorize_url,但那个值是从 CLI 看过去的(重定向到 CLI 而不是浏览器),
|
|
116
|
+
* 对「人在浏览器里点」这件事没有意义,所以只认自己拼的。
|
|
117
|
+
*
|
|
118
|
+
* 响应校验三件事,缺一即 protocol 错误:flow_id 合 FLOW_ID_PATTERN、
|
|
119
|
+
* poll_interval_sec >= 1、expires_at > 0。
|
|
120
|
+
*/
|
|
121
|
+
export declare function initStepCodeCliLogin(input: StepCodeCliLoginInitInput): Promise<StepCodeLoginInit>;
|
|
122
|
+
/** 一次轮询的三种结果(逐字 StepCliLoginPoll,login-client.ts:61-68)。 */
|
|
123
|
+
export type StepCodeLoginPoll = {
|
|
124
|
+
readonly state: 'pending';
|
|
125
|
+
} | {
|
|
126
|
+
readonly state: 'ready';
|
|
127
|
+
readonly apiKey: string;
|
|
128
|
+
readonly uid?: string;
|
|
129
|
+
} | {
|
|
130
|
+
readonly state: 'failed';
|
|
131
|
+
readonly reason: 'denied' | 'unknown';
|
|
132
|
+
};
|
|
133
|
+
export interface StepCodeCliLoginPollInput {
|
|
134
|
+
readonly profile: StepCodeProfile;
|
|
135
|
+
readonly pollToken: string;
|
|
136
|
+
readonly flowId: string;
|
|
137
|
+
readonly fetchFn?: typeof fetch;
|
|
138
|
+
readonly signal?: AbortSignal;
|
|
139
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* GET {authBase}/api/stdhttp/v1/cli-login/poll/{encodeURIComponent(flow_id)}。
|
|
143
|
+
*
|
|
144
|
+
* 三种 state 各自的下一步不同,所以分开建模:
|
|
145
|
+
*
|
|
146
|
+
* - pending:继续等。
|
|
147
|
+
* - ready:取 credential.api_key(必须非空)与**顶层**可选 uid。
|
|
148
|
+
* - failed:**只有字面 denied** 归为「用户在浏览器里拒绝了」;其余 reason 一律
|
|
149
|
+
* 归为「未知失败」——两者的下一步不同(再点一次 vs 等上游恢复)。
|
|
150
|
+
* - 其它 state:protocol 错误(对面不是我们以为的那个服务端)。
|
|
151
|
+
*
|
|
152
|
+
* 逐字照抄 login-client.ts:174-209,包括 flow_id 的二次校验:形状不对的 flow_id
|
|
153
|
+
* 说明 URL 被污染或上游改版,重发多少次都一样。
|
|
154
|
+
*/
|
|
155
|
+
export declare function pollStepCodeCliLogin(input: StepCodeCliLoginPollInput): Promise<StepCodeLoginPoll>;
|
|
156
|
+
export interface WaitForStepCodeLoginInput {
|
|
157
|
+
readonly init: StepCodeLoginInit;
|
|
158
|
+
readonly profile: StepCodeProfile;
|
|
159
|
+
readonly pollToken: string;
|
|
160
|
+
readonly fetchFn?: typeof fetch;
|
|
161
|
+
readonly signal?: AbortSignal;
|
|
162
|
+
readonly env?: NodeJS.ProcessEnv; /**
|
|
163
|
+
* 外层登录自己的截止(Unix 毫秒)。可选。
|
|
164
|
+
*
|
|
165
|
+
* 官方只有服务端 expires_at 一个截止(login-polling.ts:20-25),而外层登录另有
|
|
166
|
+
* 一个本地总时限;两个都实现时取**先到者**,否则本地时限形同虚设。
|
|
167
|
+
*/
|
|
168
|
+
readonly localDeadline?: number;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* 轮询直到拿到凭据、用户拒绝,或到达截止。
|
|
172
|
+
*
|
|
173
|
+
* 逐字照抄 login-polling.ts:21-51,包括它的两条:
|
|
174
|
+
*
|
|
175
|
+
* - 间隔 clamp 到 [1s, 60s]:上游可以让我们慢一点,但不能让一次轮询停几分钟。
|
|
176
|
+
* - 截止 = init.expiresAt * 1000(服务端的硬截止),不是本地猜测的时长;
|
|
177
|
+
* 外层登录(beginStepCodeLogin)另有自己的总时限,两者取先到者。
|
|
178
|
+
*
|
|
179
|
+
* 重试判定走 isRetryableStepCodeLoginError:可重试的错误被吞掉继续下一轮,
|
|
180
|
+
* 不可重试的直接抛出。
|
|
181
|
+
*/
|
|
182
|
+
export declare function waitForStepCodeLogin(input: WaitForStepCodeLoginInput): Promise<{
|
|
183
|
+
readonly apiKey: string;
|
|
184
|
+
readonly uid?: string;
|
|
185
|
+
}>;
|
|
186
|
+
/**
|
|
187
|
+
* 本线路落盘用的凭据形态(逐字 index.ts:301-306 的 OAuthCredentials)。
|
|
188
|
+
*
|
|
189
|
+
* 三个字段各有其存在的理由:
|
|
190
|
+
*
|
|
191
|
+
* - refresh 是**静态哨兵**(STATIC_REFRESH_TOKEN)。它不是可用的 refresh token,
|
|
192
|
+
* 而是「这份凭据没有刷新链」的显式声明——官方 refreshStepOAuth 见到不是它的
|
|
193
|
+
* refresh 就抛错,所以任何别的进程/版本都能认出这份凭据。
|
|
194
|
+
* - expires 恒为 STATIC_EXPIRES_AT(Number.MAX_SAFE_INTEGER)。它是「永不过期」的写法,
|
|
195
|
+
* **不是**异常数据:读回时不得把它当成坏值(JSON 存不下 Infinity,所以取 MAX)。
|
|
196
|
+
* - profile 是区域的唯一来源(计划 §1):api.stepfun.ai 与 api.stepfun.com 互不通用。
|
|
197
|
+
*/
|
|
198
|
+
export interface StepCodeStoredCredential {
|
|
199
|
+
readonly type: 'oauth';
|
|
200
|
+
readonly access: string;
|
|
201
|
+
readonly refresh: string;
|
|
202
|
+
readonly expires: number;
|
|
203
|
+
readonly profile: StepCodeProfile;
|
|
204
|
+
readonly uid?: string;
|
|
205
|
+
}
|
|
206
|
+
/** 从一次成功登录的结果造出凭据(uid 不合格时已经被丢掉,这里只做装配)。 */
|
|
207
|
+
export declare function stepCodeCredentialFromLogin(profile: StepCodeProfile, ready: {
|
|
208
|
+
readonly apiKey: string;
|
|
209
|
+
readonly uid?: string;
|
|
210
|
+
}): StepCodeStoredCredential;
|
|
211
|
+
/**
|
|
212
|
+
* 手动粘贴 Platform API Key(按量计费的两条 profile)造出的凭据。
|
|
213
|
+
*
|
|
214
|
+
* 形状与浏览器登录**完全一致**:同一条线路上两种来源的凭据在池里不该被区别对待
|
|
215
|
+
*(Step 的 api_key 本身就不分来源)。
|
|
216
|
+
*/
|
|
217
|
+
export declare function stepCodeCredentialFromApiKey(profile: StepCodeProfile, apiKey: string, uid?: string): StepCodeStoredCredential;
|
|
218
|
+
/** 一份值是不是本线路的凭据形态。 */
|
|
219
|
+
export declare function isStepCodeStoredCredential(value: unknown): value is StepCodeStoredCredential;
|
|
220
|
+
/** 凭据不可刷新的那句说明(号池与路由共用同一句)。 */
|
|
221
|
+
export declare const STEP_CODE_CREDENTIAL_NOT_REFRESHABLE: string;
|
|
222
|
+
/**
|
|
223
|
+
* 「刷新」这条路径的**显式拒绝**。
|
|
224
|
+
*
|
|
225
|
+
* 它必须是一个被拒绝的 Promise 而不是一次静默的空操作:调用方(号池的 refresh 钩子、
|
|
226
|
+
* 适配器的 401 处理)会把错误报给用户,而静默返回旧凭据会让一次注定失败的请求
|
|
227
|
+
* 看起来像成功了。逐字照抄官方 refreshStepOAuth(index.ts:316-321)的拒绝语义。
|
|
228
|
+
*/
|
|
229
|
+
export declare function refreshStepCodeCredential(credential: StepCodeStoredCredential): Promise<StepCodeStoredCredential>;
|
|
230
|
+
/** 卡片轮询的状态切片。返回副本,调用方改不到内部状态。 */
|
|
231
|
+
export declare function getStepCodeLoginStatus(): StepCodeLoginFlowStatus;
|
|
232
|
+
/** 取消进行中的流程并回到 idle(设置卡片的「取消」)。 */
|
|
233
|
+
export declare function resetStepCodeLogin(): void;
|
|
234
|
+
/** 看看有没有一份已经拿到、还没被取走的凭据(纯内存读)。 */
|
|
235
|
+
export declare function peekStepCodeLoginCredential(): StepCodeStoredCredential | null;
|
|
236
|
+
/** 取走那份凭据并清空(同一份凭据只该被落盘一次)。 */
|
|
237
|
+
export declare function takeStepCodeLoginCredential(): StepCodeStoredCredential | null;
|
|
238
|
+
export interface StepCodeLoginOptions {
|
|
239
|
+
/** 测试缝。默认 fetch。 */
|
|
240
|
+
fetchFn?: typeof fetch;
|
|
241
|
+
env?: NodeJS.ProcessEnv;
|
|
242
|
+
/** 审计信息;缺省用 version 造一个(version 缺省是 unknown)。 */
|
|
243
|
+
client?: StepCodeClientInfo;
|
|
244
|
+
version?: string;
|
|
245
|
+
/**
|
|
246
|
+
* 完成的登录写到哪里(接入层传号池或凭据存储的保存函数)。
|
|
247
|
+
*
|
|
248
|
+
* 没有它时凭据只是留在内存里,等 takeStepCodeLoginCredential() 取走——
|
|
249
|
+
* 本模块**不持有凭据存储**,所以不替接入层猜该写哪儿。
|
|
250
|
+
*/
|
|
251
|
+
onSave?: (credential: StepCodeStoredCredential) => Promise<unknown>;
|
|
252
|
+
/** 本地总时限;缺省 10 分钟,可由 STEP_OAUTH_TIMEOUT_MS 覆盖。 */
|
|
253
|
+
timeoutMs?: number;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* 开始一次云端轮询登录:**不开本地端口**,用户去浏览器里人工确认。
|
|
257
|
+
*
|
|
258
|
+
* 流程跑在 host 上(controller + flow),设置卡片只跟随 getStepCodeLoginStatus——
|
|
259
|
+
* 与其余各线路的登录面同构。
|
|
260
|
+
*
|
|
261
|
+
* 两个截止取先到者:上游的 expires_at(硬截止,逐字 login-polling.ts:20-25)
|
|
262
|
+
* 与本地总时限(默认 10 分钟,可由 STEP_OAUTH_TIMEOUT_MS 覆盖)。
|
|
263
|
+
*/
|
|
264
|
+
export declare function beginStepCodeLogin(profile: StepCodeProfile, options?: StepCodeLoginOptions): Promise<StepCodeLoginFlowStatus>;
|
|
265
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../../src/host/step-code/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step Code(Step Plan 订阅)线路的 web 路由。
|
|
3
|
+
*
|
|
4
|
+
* 路由表与客户端 `src/client/step-code/api.ts` 里那一份是**同一个约定**,两边必须逐条对上:
|
|
5
|
+
*
|
|
6
|
+
* ```
|
|
7
|
+
* GET /status -> StepCodeStatusDto(页面的唯一读口)
|
|
8
|
+
* POST /settings StepCodeSettingsUpdateDto -> StepCodeStatusDto
|
|
9
|
+
* POST /accounts { action, accountId } / { action:'strategy', strategy } -> StepCodeStatusDto
|
|
10
|
+
* POST /login/start { profile } -> StepCodeLoginFlowStatus
|
|
11
|
+
* GET /login/status -> StepCodeLoginFlowStatus
|
|
12
|
+
* POST /login/cancel { } -> StepCodeLoginFlowStatus
|
|
13
|
+
* POST /login/manual { profile, apiKey } -> StepCodeStatusDto(请求体带凭据,不在冻结契约里)
|
|
14
|
+
* POST /adopt { } -> StepCodeAdoptResultDto
|
|
15
|
+
* POST /connection/test { } -> StepCodeConnectionDto
|
|
16
|
+
* POST /quota { } -> StepCodeStatusDto(强制刷新额度)
|
|
17
|
+
* POST /catalog/refresh { } -> StepCodeStatusDto
|
|
18
|
+
* POST /quota/credential { mode:'password'|'manual'|'clear', account?, password?, token? } -> StepCodeStatusDto
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* 信封:除 `/adopt` 与 `/connection/test` 外一律 `{ ok, value }`,因为客户端走的
|
|
22
|
+
* `createLineApi` 会把信封拆掉、直接把 `value` 当 DTO 用;这两条路由的契约把 DTO 定在
|
|
23
|
+
* 顶层,所以它们**直接**返回 DTO(`createLineApi` 对没有布尔 `ok` 的应答原样返回整体)。
|
|
24
|
+
*
|
|
25
|
+
* 同源校验不可省:每个 POST 都过 `isSameOriginMutation`,与兄弟线路同一份实现。
|
|
26
|
+
*
|
|
27
|
+
* 本文件**不持有任何凭据,也不算任何用量**:落盘与兑换交给 token-store / account-pool /
|
|
28
|
+
* oauth / adopt,上游 I/O 交给 client.ts,额度快照的累计交给 adapter.ts 的缓存累计器。
|
|
29
|
+
* 它只做三件事:读设置、组装状态面、把同源的 POST 翻译成对上面那些模块的一次调用。
|
|
30
|
+
*/
|
|
31
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
32
|
+
import type { AccountRotationStrategy } from '../../shared/account-pool-contracts.ts';
|
|
33
|
+
import { type StepCodeAccountSummaryDto, type StepCodeCacheStatsDto, type StepCodeProfile, type StepCodeQuotaCredentialStatusDto, type StepCodeQuotaSnapshotDto, type StepCodeStatusDto } from '../../shared/step-code-contracts.ts';
|
|
34
|
+
import { type StepCodeAccountPool } from './account-pool.ts';
|
|
35
|
+
import { type StepCodeModelEntry } from './model-catalog.ts';
|
|
36
|
+
import { StepCodeModelSettingsStore, StepCodeQuotaCredentialStore, type StepCodeModelSettings, type StepCodePreferenceStore, type StepCodeSettingsPatch } from './token-store.ts';
|
|
37
|
+
/** 一个请求寻址的子路径(剥掉契约前缀)。 */
|
|
38
|
+
export declare function stepCodeSubPathOf(requestUrl: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* 设置来源:register 后端与文件后端形状不同,这里收敛成一个。
|
|
41
|
+
*
|
|
42
|
+
* `status()` 允许是 promise:文件后端要读盘,而卡片每 60 秒轮询一次状态。
|
|
43
|
+
* register 后端同步返回,实现方不必知道自己被允许同步。
|
|
44
|
+
*/
|
|
45
|
+
export interface StepCodeSettingsSource {
|
|
46
|
+
status(): StepCodeModelSettings | Promise<StepCodeModelSettings>;
|
|
47
|
+
update(patch: StepCodeSettingsPatch): Promise<StepCodeModelSettings>;
|
|
48
|
+
}
|
|
49
|
+
/** 设置来源:register 后端优先,没有就落回凭据旁边的 JSON 文件。 */
|
|
50
|
+
export declare function stepCodeSettingsSource(preferences: StepCodePreferenceStore | undefined, fallback: StepCodeModelSettingsStore): StepCodeSettingsSource;
|
|
51
|
+
/**
|
|
52
|
+
* 用平台默认浏览器打开一个 URL(尽力而为)。
|
|
53
|
+
*
|
|
54
|
+
* 与其余各线路同一份形状。启动失败是可恢复的:同一个 URL 始终在登录状态里,
|
|
55
|
+
* 卡片也把它渲染成一个可点的链接,所以这里**永远不抛**。
|
|
56
|
+
*/
|
|
57
|
+
/**
|
|
58
|
+
* 用系统默认程序打开一个 URL。
|
|
59
|
+
*
|
|
60
|
+
* 它**不是**默认行为(见下面 `registerStepCodeRoutes` 里那句「缺省不开浏览器」):
|
|
61
|
+
* 授权页由设置卡片自己打开,host 只在显式注入 `openBrowser` 时才代劳——需要这种行为的
|
|
62
|
+
* 部署可以直接把这个函数作为注入口传进去,而不是让每条线路各自复制一份 spawn 逻辑。
|
|
63
|
+
*/
|
|
64
|
+
export declare function openPlatformBrowser(url: string): void;
|
|
65
|
+
export interface StepCodeRouteOptions {
|
|
66
|
+
fetchFn?: typeof fetch;
|
|
67
|
+
/** 本插件是否正在服务这条 Provider 路由;每次状态都重新读。 */
|
|
68
|
+
serving?: boolean | (() => boolean);
|
|
69
|
+
/** 路由被别的适配器占用时的诊断文案;每次状态都重新读。 */
|
|
70
|
+
conflict?: string | null | (() => string | null);
|
|
71
|
+
/** 号池;本进程装了才有。 */
|
|
72
|
+
accountPool?: StepCodeAccountPool;
|
|
73
|
+
/** 额度凭据的存储;缺省按平台加密矩阵落在自己的文件上。 */
|
|
74
|
+
quotaCredentialStore?: StepCodeQuotaCredentialStore;
|
|
75
|
+
/**
|
|
76
|
+
* 打开授权页的方式;缺省用平台默认浏览器。
|
|
77
|
+
*
|
|
78
|
+
* 显式传入一个空函数就把这条外部副作用整个摘掉(测试的用法,与 GLM 的注入口同形)。
|
|
79
|
+
* 卡片自己也会 `window.open` 同一个链接,所以注入空函数就能只留一处开浏览器的地方。
|
|
80
|
+
*/
|
|
81
|
+
openBrowser?: (url: string) => void;
|
|
82
|
+
/** 环境变量读取处;缺省 process.env,且**调用时**读取。 */
|
|
83
|
+
env?: NodeJS.ProcessEnv;
|
|
84
|
+
}
|
|
85
|
+
/** 号池切片的收紧形状(本线路状态面实际持有的那一部分)。 */
|
|
86
|
+
export interface StepCodePoolSlice {
|
|
87
|
+
accounts: StepCodeAccountSummaryDto[];
|
|
88
|
+
rotationStrategy: AccountRotationStrategy;
|
|
89
|
+
activeAccountId?: string;
|
|
90
|
+
}
|
|
91
|
+
export interface StepCodeStatusSources {
|
|
92
|
+
options: StepCodeRouteOptions;
|
|
93
|
+
settings: StepCodeSettingsSource;
|
|
94
|
+
/** 下一次登录要用的 profile(区域由它唯一决定)。 */
|
|
95
|
+
profile: StepCodeProfile;
|
|
96
|
+
/** 号池切片:唯一装配它的地方是 account-pool 的 stepCodePoolStatusSlice(这里只收紧形状)。 */
|
|
97
|
+
pool: StepCodePoolSlice;
|
|
98
|
+
/** 本次读到的账号(卡片渲染用,不带任何凭据)。 */
|
|
99
|
+
account: StepCodeAccountSummaryDto | null;
|
|
100
|
+
/** 这个部署当前的模型目录(缓存读,轮询不联网)。 */
|
|
101
|
+
catalog: readonly StepCodeModelEntry[];
|
|
102
|
+
/** 本进程为当前账号记住的额度快照。 */
|
|
103
|
+
quota: StepCodeQuotaSnapshotDto | null;
|
|
104
|
+
/** 额度凭据的状态切片。 */
|
|
105
|
+
quotaCredential: StepCodeQuotaCredentialStatusDto;
|
|
106
|
+
/** 本次应答背后是否正在刷新额度。 */
|
|
107
|
+
quotaRefreshing: boolean;
|
|
108
|
+
/** 上一次额度读失败的原因;没有快照可渲染时为 null。 */
|
|
109
|
+
quotaError: string | null;
|
|
110
|
+
/** 本进程累计的缓存用量;尚无样本时为 undefined(客户端据此渲染占位符)。 */
|
|
111
|
+
cacheStats: StepCodeCacheStatsDto | undefined;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 组装 `StepCodeStatusDto`。
|
|
115
|
+
*
|
|
116
|
+
* 号池读不出来不能带倒整张卡:连接那一半仍然值得渲染,只是账号列表是空的。
|
|
117
|
+
*/
|
|
118
|
+
export declare function getStepCodeStatus(sources: StepCodeStatusSources): Promise<StepCodeStatusDto>;
|
|
119
|
+
/**
|
|
120
|
+
* 注册本线路的路由。
|
|
121
|
+
*
|
|
122
|
+
* 本文件不持有凭据:账号的落盘与轮转在号池,额度凭据在它自己那份加密存储里,
|
|
123
|
+
* 而线路凭据由号池镜像。设置的唯一写入点是 `POST /settings`。
|
|
124
|
+
*/
|
|
125
|
+
export declare function registerStepCodeRoutes(ctx: Context, settings: StepCodeSettingsSource, options?: StepCodeRouteOptions): () => void;
|
|
126
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../../src/host/step-code/routes.ts"],"names":[],"mappings":"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"}
|