@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.
Files changed (85) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +56 -3
  3. package/lib/client.js +2719 -491
  4. package/lib/client.js.map +1 -1
  5. package/lib/index.js +8041 -3092
  6. package/lib/types/client/glm-coding-plan/GlmCodingPlanSection.d.ts.map +1 -1
  7. package/lib/types/client/glm-coding-plan/locales.d.ts +17 -26
  8. package/lib/types/client/glm-coding-plan/locales.d.ts.map +1 -1
  9. package/lib/types/client/glm-coding-plan/styles.d.ts +2 -2
  10. package/lib/types/client/glm-coding-plan/styles.d.ts.map +1 -1
  11. package/lib/types/client/hub/brand-icons.d.ts +2 -2
  12. package/lib/types/client/hub/brand-icons.d.ts.map +1 -1
  13. package/lib/types/client/hub/providers.d.ts.map +1 -1
  14. package/lib/types/client/index.d.ts +2 -0
  15. package/lib/types/client/index.d.ts.map +1 -1
  16. package/lib/types/client/ollama/OllamaSection.d.ts.map +1 -1
  17. package/lib/types/client/ollama/api.d.ts +13 -0
  18. package/lib/types/client/ollama/api.d.ts.map +1 -1
  19. package/lib/types/client/ollama/locales.d.ts +24 -0
  20. package/lib/types/client/ollama/locales.d.ts.map +1 -1
  21. package/lib/types/client/step-code/StepCodeComposerQuota.d.ts +52 -0
  22. package/lib/types/client/step-code/StepCodeComposerQuota.d.ts.map +1 -0
  23. package/lib/types/client/step-code/StepCodeSection.d.ts +28 -0
  24. package/lib/types/client/step-code/StepCodeSection.d.ts.map +1 -0
  25. package/lib/types/client/step-code/api.d.ts +4 -0
  26. package/lib/types/client/step-code/api.d.ts.map +1 -0
  27. package/lib/types/client/step-code/locales.d.ts +648 -0
  28. package/lib/types/client/step-code/locales.d.ts.map +1 -0
  29. package/lib/types/client/step-code/styles.d.ts +28 -0
  30. package/lib/types/client/step-code/styles.d.ts.map +1 -0
  31. package/lib/types/client/step-code/useStepCodeSection.d.ts +122 -0
  32. package/lib/types/client/step-code/useStepCodeSection.d.ts.map +1 -0
  33. package/lib/types/host/antigravity/account-pool.d.ts.map +1 -1
  34. package/lib/types/host/common/account-pool.d.ts +38 -3
  35. package/lib/types/host/common/account-pool.d.ts.map +1 -1
  36. package/lib/types/host/common/model-request-control.d.ts +1 -1
  37. package/lib/types/host/common/model-request-control.d.ts.map +1 -1
  38. package/lib/types/host/common/request-diagnostics.d.ts +1 -1
  39. package/lib/types/host/common/request-diagnostics.d.ts.map +1 -1
  40. package/lib/types/host/glm-coding-plan/account-pool.d.ts.map +1 -1
  41. package/lib/types/host/glm-coding-plan/adapter.d.ts +1 -14
  42. package/lib/types/host/glm-coding-plan/adapter.d.ts.map +1 -1
  43. package/lib/types/host/glm-coding-plan/client.d.ts.map +1 -1
  44. package/lib/types/host/glm-coding-plan/types.d.ts +0 -10
  45. package/lib/types/host/glm-coding-plan/types.d.ts.map +1 -1
  46. package/lib/types/host/ollama/adapter.d.ts +26 -2
  47. package/lib/types/host/ollama/adapter.d.ts.map +1 -1
  48. package/lib/types/host/ollama/client.d.ts +16 -1
  49. package/lib/types/host/ollama/client.d.ts.map +1 -1
  50. package/lib/types/host/ollama/routes.d.ts +1 -1
  51. package/lib/types/host/ollama/routes.d.ts.map +1 -1
  52. package/lib/types/host/ollama/types.d.ts +74 -8
  53. package/lib/types/host/ollama/types.d.ts.map +1 -1
  54. package/lib/types/host/step-code/account-pool.d.ts +187 -0
  55. package/lib/types/host/step-code/account-pool.d.ts.map +1 -0
  56. package/lib/types/host/step-code/adapter.d.ts +142 -0
  57. package/lib/types/host/step-code/adapter.d.ts.map +1 -0
  58. package/lib/types/host/step-code/adopt.d.ts +201 -0
  59. package/lib/types/host/step-code/adopt.d.ts.map +1 -0
  60. package/lib/types/host/step-code/cache-stats.d.ts +181 -0
  61. package/lib/types/host/step-code/cache-stats.d.ts.map +1 -0
  62. package/lib/types/host/step-code/client.d.ts +331 -0
  63. package/lib/types/host/step-code/client.d.ts.map +1 -0
  64. package/lib/types/host/step-code/mapper.d.ts +301 -0
  65. package/lib/types/host/step-code/mapper.d.ts.map +1 -0
  66. package/lib/types/host/step-code/model-catalog.d.ts +230 -0
  67. package/lib/types/host/step-code/model-catalog.d.ts.map +1 -0
  68. package/lib/types/host/step-code/oauth.d.ts +265 -0
  69. package/lib/types/host/step-code/oauth.d.ts.map +1 -0
  70. package/lib/types/host/step-code/routes.d.ts +126 -0
  71. package/lib/types/host/step-code/routes.d.ts.map +1 -0
  72. package/lib/types/host/step-code/token-store.d.ts +325 -0
  73. package/lib/types/host/step-code/token-store.d.ts.map +1 -0
  74. package/lib/types/host/step-code/types.d.ts +488 -0
  75. package/lib/types/host/step-code/types.d.ts.map +1 -0
  76. package/lib/types/host/workbuddy/adapter.d.ts.map +1 -1
  77. package/lib/types/index.d.ts +5 -1
  78. package/lib/types/index.d.ts.map +1 -1
  79. package/lib/types/shared/ollama-contracts.d.ts +30 -0
  80. package/lib/types/shared/ollama-contracts.d.ts.map +1 -1
  81. package/lib/types/shared/step-code-contracts.d.ts +438 -0
  82. package/lib/types/shared/step-code-contracts.d.ts.map +1 -0
  83. package/package.json +1 -1
  84. package/lib/types/host/glm-coding-plan/signing.d.ts +0 -323
  85. package/lib/types/host/glm-coding-plan/signing.d.ts.map +0 -1
@@ -1,323 +0,0 @@
1
- /**
2
- * GLM(ZCode 账号)线路的 Client Request Signing V4(计划 §6.1 的 `signing.ts`,工作包 W4)。
3
- *
4
- * ## 一句话说清它的地位:这一层**默认关闭**,而且它不进入默认路径
5
- *
6
- * 唯一有真实调用记录的实现(hj01857655/ZCode)做过 A/B 对照:**带签名与不带签名的响应
7
- * 归一化后完全一致**(都是 HTTP 429 / 业务码 1113「没有余额也没有可用的资源包」)。
8
- * 也就是说:
9
- *
10
- * - 没有人观察到服务端因为**缺**签名而拒绝请求;
11
- * - 也没有一份证据能证明带签名能换到额外额度(参考实现注释里说的「150% 额度 / 夜间免费
12
- * Flash」是它的**声称**,不是实测结论)。
13
- *
14
- * 按计划的证据分级(§2)这属于 **C 级 = 社区经验或架构推断,无实测**,实施规则是
15
- * 「**实现但默认不启用**,做对照实验」。所以:
16
- *
17
- * 1. `CLIENT_SIGNING_DEFAULT_ENABLED = false`(`types.ts`,冻结),本文件不重定义它;
18
- * 2. `buildSigningHeaders()` 是**唯一对外的签名入口**,它在门控关闭时返回空表并且
19
- * **一次网络请求都不发**——这是结构性保证,不是靠调用方自觉;
20
- * 3. 门控由 `types.ts` 的 `clientSigningEnabled(env)` 读 `DSH_GLM_CLIENT_SIGNING=1` 打开。
21
- *
22
- * 门控关掉之后,`applyGlmClientSigning()` 拿到一个空表,调用方的请求头**一个键都不会变**。
23
- *
24
- * ## 实现来源与许可
25
- *
26
- * 移植自 MIT 许可的现成实现(本身就是 DSH 插件里的 TS 文件,纯 `node:crypto` 零依赖):
27
- *
28
- * - 来源:<https://raw.githubusercontent.com/ShanWuYinShe/dsh-plugins/main/packages/dsh-any-connect/src/zcode-signer.ts>
29
- * (仓库 ShanWuYinShe/dsh-plugins,路径 `packages/dsh-any-connect/src/zcode-signer.ts`,219 行)
30
- * - 许可:**MIT**(计划 R7:只有 MIT 仓库可以复制代码;bacnh85/pi-extensions 与
31
- * TriDefender/zcode-api 的许可为 null,只读协议、照协议重写)
32
- * - 随附参考测试:同仓库 `test/zcode-signer.test.ts`
33
- *
34
- * 协议逐字要点(与上实现一致,本文件未改动算法):
35
- *
36
- * - 握手:`POST {握手 origin}/api/paas/c1f3a7e2/v2/client`,头 `Authorization: {apiKeyId}.{apiKeySecret}`
37
- * (**裸 Key,不加 Bearer**),体四字段 `{apiKey, nonce, sig, ts}`
38
- * - 密钥派生:HKDF-SHA256,`salt = 'WD_CLIENT_SIGN_KDF_SALT'`,`info = 'getSignKey_hmac'`(导出
39
- * HMAC 密钥)/ `'ed25519_priv'`(导出解私钥用的 AES-GCM 密钥),长度均为 32 字节
40
- * - HMAC 消息:`"get_sign_key\n{apiKeyId}\n{ts}\n{nonce}"`,**换行分隔**(空格分隔会被拒),
41
- * 结果 base64
42
- * - 响应 `data.privateCipher` → AES-256-GCM 解密,iv 取前 12 字节、tag 取末 16 字节、
43
- * AAD = apiKeyId;解密出的明文**又是 base64** 的 PKCS#8 Ed25519 私钥(双层编码)
44
- * - 业务签名消息:`"{apiKeyId}\n{ts}\n{clientVersion}\n{sessionId}\n{nonce}"`,Ed25519 签名后
45
- * **base64**(不是 hex)
46
- * - PoW:`sha256("{apiKeyId}\n{appId}\n{sessionId}\n{ts}")` 的 hex 取**前 32 字符**作 seed,
47
- * 在 `sha256("{seed}\n{nonce}{counter hex 8 位}")` 上找前导 0 位 >= 8 的解
48
- * - App id = `'zcode'`
49
- *
50
- * ## 相对参考实现改掉的三处(计划 R2 / 任务书,逐条对应)
51
- *
52
- * 1. **握手 origin 改成 `https://api.z.ai`。**
53
- * 参考实现硬编码 `open.bigmodel.cn`,但实测记录逐字写着「`/api/paas/*` 在 zcode.z.ai 上
54
- * 404,get_sign_key 端点回应在 api.z.ai 这个 origin」(计划 R2)。本线路默认用 api.z.ai,
55
- * 并按 `types.ts` 的覆盖写法接受 `DSH_GLM_SIGN_HANDSHAKE_BASE` /
56
- * `DSH_GLM_SIGN_HANDSHAKE_URL` 覆盖(读取发生在调用时,不是模块加载时)。
57
- * 2. **clientVersion 默认提到 `3.15.1`**(参考实现是 `3.4.0`)。这个值同时进签名串与
58
- * `X-Client-Version` / `X-ZCode-App-Version` / `User-Agent` 三个头,写错签名直接失效;
59
- * TriDefender 的测试注释称 3.15.1 起 `/api/v1/agent/configs` 这个 gate 已移除。
60
- * 默认值可被 `DSH_GLM_SIGN_CLIENT_VERSION` 覆盖。
61
- * 3. **不移植 gate 逻辑。** 第二参考实现(pi-extensions,许可 null,只读协议)里有
62
- * 「先探 `/api/v1/agent/configs` 决定要不要签名」的门控,本线路**不做这个探测**:
63
- * 计划已把门控收敛成「默认关闭 + `DSH_GLM_CLIENT_SIGNING` 显式打开」,
64
- * 多一次探测就多一个会失败的上游依赖。
65
- *
66
- * ## 另外三处刻意偏离参考实现(理由随代码给出)
67
- *
68
- * - **不发 `Authorization`。** 参考实现返回的表里带 `Authorization: Bearer {id}.{secret}`,
69
- * 但本线路模型面的认证头是 W5/W6 的活,且 Anthropic 面要求**双头**
70
- * (`x-api-key` + `Authorization: Bearer` 同值,计划 §3.3 逐字引用官方注释)。
71
- * 签名器若顺手覆盖 `Authorization`,会把装配层算好的认证头顶掉,所以这一行不归它。
72
- * - **默认不覆盖调用方的 `User-Agent`。** `types.ts` 的 `USER_AGENT` 明写「如实报成这个
73
- * 第三方插件,不冒充官方客户端」。`buildSigningHeaders()` 作为原样移植仍然返回
74
- * `ZCode/{version}`,但 `applyGlmClientSigning()` 默认保留调用方已有的 `User-Agent`,
75
- * 要替换得显式传 `overrideUserAgent: true`。签名层本身整层都是「假装成官方客户端」,
76
- * 这道默认值让「开签名」不必等于「改身份」。
77
- * - **成功码同时认 `0` 与 `200`。** 参考实现只认 `code === 200`;本线路业务面信封把两者都
78
- * 当成功(见 `exchange.ts` 的 `isBizSuccessCode`),握手面在同一个 origin 上,只认一个会
79
- * 凭空制造一次失败。
80
- *
81
- * ## 未验证(缺什么证据)
82
- *
83
- * - 握手路径里的 `c1f3a7e2` 是否会轮换(计划 §9 明确未验证第 2 条)。缺一份上游变更通告,
84
- * 所以路径做成常量 + URL 覆盖。
85
- * - 私钥是否长期稳定:没有任何证据说服务端会为同一把 Coding Plan Key 重新下发私钥,
86
- * 因此这里按「一把凭据一把私钥」缓存到进程结束,W6 换凭据时应调 `clearPrivateKey()`。
87
- * - 明文**直接是 DER**(不做 base64)的形状没有证据;这里按 ASN.1 首字节做一次形状判定,
88
- * 两种形状都能解开,但只有 base64 双层那一种是参考实现实测过的。
89
- * - `X-Title: 'Z Code@cli'` / `X-Release-Channel: 'stable'` / `X-ZCode-Agent: 'glm'` 三个头
90
- * 是否参与签名校验无从判断;它们原样保留参考实现的取值,未做删减实验。
91
- * - 服务端是否真的因缺签名返回 `VERIFY_SIGNATURE_INVALID`:**从未被观察到**(计划 §9 末条)。
92
- */
93
- /** HKDF 的 salt,逐字来自参考实现的 `KDF_SALT`。 */
94
- export declare const SIGNING_KDF_SALT = "WD_CLIENT_SIGN_KDF_SALT";
95
- /** 导出 HMAC 密钥的 HKDF info,逐字来自参考实现的 `INFO_HMAC`。 */
96
- export declare const SIGNING_INFO_HMAC = "getSignKey_hmac";
97
- /** 导出「解私钥用的 AES-GCM 密钥」的 HKDF info,逐字来自参考实现的 `INFO_PRIV`。 */
98
- export declare const SIGNING_INFO_PRIV = "ed25519_priv";
99
- /** HMAC 消息的第一行,逐字来自参考实现。**换行分隔**,空格分隔会被服务端拒。 */
100
- export declare const SIGNING_HMAC_PREFIX = "get_sign_key";
101
- /** App id。国区授权入口的 `appId` 与这里同值(`bigmodelProviderConfig.ts:19-20,24`)。 */
102
- export declare const SIGNING_APP_ID = "zcode";
103
- /**
104
- * 默认 clientVersion:`3.15.1`。
105
- *
106
- * 参考实现用的是 `3.4.0`,必须提上来——这个值同时进签名串与三个版本头,写错签名直接失效。
107
- * 取 `3.15.1` 的依据是 TriDefender 测试注释里那条「3.15.1 起 `/api/v1/agent/configs`
108
- * gate 已移除」,它是证据里出现过的唯一版本号。
109
- *
110
- * **未验证**:更大的版本号是否被接受、上游当前的实际版本是多少,都没有任何实测样本。
111
- * 缺一份真实请求的版本头观测。
112
- */
113
- export declare const SIGNING_CLIENT_VERSION_DEFAULT = "3.15.1";
114
- /**
115
- * 握手 origin 默认值:**api.z.ai**。
116
- *
117
- * 参考实现硬编码 `open.bigmodel.cn`,但实测记录逐字写着「`/api/paas/*` 在 zcode.z.ai 上 404,
118
- * get_sign_key 端点回应在 api.z.ai 这个 origin」(计划 R2)。本线路默认用 api.z.ai。
119
- *
120
- * **未验证**:国区(open.bigmodel.cn)是否也提供这个握手端点,没有实测样本。
121
- * 部署在国区时用 `DSH_GLM_SIGN_HANDSHAKE_BASE` 指过去。
122
- */
123
- export declare const SIGNING_HANDSHAKE_ORIGIN_DEFAULT = "https://api.z.ai";
124
- /** 握手路径(逐字来自参考实现)。**未验证**:`c1f3a7e2` 是否会轮换(计划 §9 第 2 条)。 */
125
- export declare const SIGNING_HANDSHAKE_PATH = "/api/paas/c1f3a7e2/v2/client";
126
- /** PoW 默认难度:要求答案摘要前导 0 位 >= 8(即 `digest[0] === 0`)。 */
127
- export declare const SIGNING_POW_BITS_DEFAULT = 8;
128
- /** PoW 的 seed 取 sha256 hex 的前 32 个字符(不是前 16 字节,这是原样的十六进制字符切片)。 */
129
- export declare const SIGNING_POW_SEED_HEX_LENGTH = 32;
130
- /**
131
- * 握手超时。与其余上游端点「响应头 30s」同口径(沿用参考实现的 `HANDSHAKE_TIMEOUT_MS`,
132
- * 与 `types.ts` 的 `OAUTH_REQUEST_TIMEOUT_MS` 同为 30s)。
133
- *
134
- * 握手必须自己兜超时:它发生在一次模型请求之前,调用方传下来的 `signal` 与业务超时口径
135
- * 未必覆盖到这里;不设上界时握手端点挂死会把整条请求挂到 undici 的默认 headersTimeout。
136
- */
137
- export declare const SIGNING_HANDSHAKE_TIMEOUT_MS = 30000;
138
- /** 签名层的任何失败都抛这一类,调用方按「签名不可用」降级(关闭该功能,而不是让请求整体失败)。 */
139
- export declare class GlmSigningError extends Error {
140
- constructor(message: string, options?: {
141
- cause?: unknown;
142
- });
143
- }
144
- /** 一把 Coding Plan Key 拆开后的三份东西:id、secret、以及拼回去的裸值。 */
145
- export interface GlmCodingPlanApiKey {
146
- apiKeyId: string;
147
- apiKeySecret: string;
148
- /** `{apiKeyId}.{apiKeySecret}`,即 Authorization 头与体 `apiKey` 字段要用的原值。 */
149
- credential: string;
150
- }
151
- /**
152
- * 拆 `{apiKeyId}.{apiKeySecret}`。
153
- *
154
- * 严格只允许**一个**点:secret 里再有点会被判为非法,而不是悄悄把后面的部分截掉——
155
- * 上游对畸形 Key 的处置是 401(`ERROR_CODE.AUTH_INVALID`),本地早失败比发一次注定失败的
156
- * 握手请求好。返回值里没有 secret 之外的东西,日志里不要打印它。
157
- */
158
- export declare function parseGlmCodingPlanApiKey(raw: string): GlmCodingPlanApiKey | undefined;
159
- /**
160
- * 握手 origin:`DSH_GLM_SIGN_HANDSHAKE_BASE` 覆盖,默认 `https://api.z.ai`。
161
- *
162
- * 做成 origin 而不是整串 URL,是为了让「换个部署/反代根」这件事与 `types.ts` 里
163
- * `businessHost` / `apiBaseForRegion` 的形状一致;路径部分是常量。
164
- */
165
- export declare function signingHandshakeOrigin(env?: NodeJS.ProcessEnv): string;
166
- /**
167
- * 握手完整 URL。
168
- *
169
- * `DSH_GLM_SIGN_HANDSHAKE_URL`(整串覆盖)优先于 `DSH_GLM_SIGN_HANDSHAKE_BASE`。
170
- * 单独留一个整串覆盖是因为 `c1f3a7e2` 这段路径**是否会轮换没有验证**(计划 §9 第 2 条),
171
- * 上游一旦换路径,只改环境变量就能救,不必发一个版本。
172
- */
173
- export declare function signingHandshakeUrl(env?: NodeJS.ProcessEnv): string;
174
- /** 签名用的 clientVersion:`DSH_GLM_SIGN_CLIENT_VERSION` 覆盖,默认 `3.15.1`。 */
175
- export declare function signingClientVersion(env?: NodeJS.ProcessEnv): string;
176
- export interface GlmSigningPowInput {
177
- apiKeyId: string;
178
- /** 缺省 `'zcode'`。 */
179
- appId?: string;
180
- sessionId: string;
181
- ts: string;
182
- /** 前导 0 位个数,缺省 8。 */
183
- powBits?: number;
184
- /** 测试缝:固定 nonce 前缀(生产不传,用 12 字节随机)。 */
185
- noncePrefix?: string;
186
- }
187
- /**
188
- * PoW 的 seed:`sha256("{apiKeyId}\n{appId}\n{sessionId}\n{ts}")` 的 hex 前 32 个字符。
189
- *
190
- * 单独抽出来是因为它同时是**签名前的诊断信息**:seed 算错时 PoW 必然解不出,
191
- * 而解不出与「难度太高」是两种完全不同的故障。
192
- */
193
- export declare function signingPowSeed(input: {
194
- apiKeyId: string;
195
- appId?: string;
196
- sessionId: string;
197
- ts: string;
198
- }): string;
199
- /**
200
- * 解 PoW:找一个让 `sha256("{seed}\n{nonce}{counter}")` 前导 0 位 >= powBits 的 `{nonce}{counter}`。
201
- *
202
- * 答案的形状是 24 个字符的随机 nonce + 8 位十六进制计数器(原样照抄参考实现)。
203
- * 8 位难度平均 256 次尝试、12 位平均 4096 次,都是纯 CPU 的小量级,不构成请求路径上的负担;
204
- * 上游要更高难度时改 `powBits` 即可,本文件不做「自适应难度」。
205
- */
206
- export declare function solveSigningProofOfWork(input: GlmSigningPowInput): string;
207
- export interface GlmClientSignerOptions {
208
- /** 缺省 `fetch`。测试注入 mock。 */
209
- fetchFn?: typeof fetch;
210
- /** 缺省 `process.env`。测试注入 `{}` / 自造环境。 */
211
- env?: NodeJS.ProcessEnv;
212
- /** 握手超时,缺省 `SIGNING_HANDSHAKE_TIMEOUT_MS`。 */
213
- handshakeTimeoutMs?: number;
214
- }
215
- export interface GlmSigningInput {
216
- /** `{apiKeyId}.{apiKeySecret}`。 */
217
- apiKey: string;
218
- /** 缺省 `crypto.randomUUID()`。同一会话内多次调用应当复用同一个 sessionId。 */
219
- sessionId?: string;
220
- /** 缺省读 `signingClientVersion(env)`。 */
221
- clientVersion?: string;
222
- /** 缺省 `'zcode'`。 */
223
- appId?: string;
224
- /** PoW 难度,缺省 8。 */
225
- powBits?: number;
226
- /** 透传给握手 fetch 的取消信号。 */
227
- signal?: AbortSignal;
228
- }
229
- /** 签名头表。空表 = 签名层关闭(门控的唯一对外表现)。 */
230
- export type GlmSigningHeaders = Record<string, string>;
231
- /**
232
- * 一把 Coding Plan Key 的签名器。
233
- *
234
- * **实例化而不是模块级单例**:一个号池可以同时持有两区多个账号(计划 §1、§8.2),
235
- * 而握手结果与私钥都是**按凭据**缓存的,单例会把第二个账号的私钥混进第一个账号的缓存。
236
- *
237
- * 但缓存只在实例内:模块级表会让 `{id}.{secret}` 这种含密的值在进程里长期驻留,
238
- * 而它并不需要跨实例复用——W6 建一个签名器用到底即可(同 `biz-token-cache.ts` 的取舍理由)。
239
- *
240
- * W5/W6 不应直接构造本类,请走 `applyGlmClientSigning()`(受门控)。
241
- */
242
- export declare class GlmClientSigner {
243
- private readonly env;
244
- private readonly fetchFn;
245
- private readonly handshakeTimeoutMs;
246
- /** 已解出的私钥(PKCS#8 DER),按裸凭据分桶。 */
247
- private readonly privateKeys;
248
- /** 在飞的握手,按裸凭据分桶:并发调用只打一次上游。 */
249
- private readonly handshakes;
250
- constructor(options?: GlmClientSignerOptions);
251
- /** 本实例当前会打的握手 URL(诊断用,设置卡片展示「签名会打到哪里」)。 */
252
- get handshakeUrl(): string;
253
- /**
254
- * 拿到这把凭据的 Ed25519 私钥(PKCS#8 DER),必要时先握手一次。
255
- *
256
- * 缓存策略是「一把凭据一把私钥,直到 `clearPrivateKey()`」。
257
- * **未验证**:服务端会不会为同一把 Coding Plan Key 重新下发私钥,没有任何证据;
258
- * 若上游轮换私钥,症状会是「签名被拒」,处置是调 `clearPrivateKey()` 让它重握手。
259
- *
260
- * 这是低层原语,**不受门控**——门控在唯一对外的 `buildSigningHeaders()` 上。
261
- */
262
- ensurePrivateKey(apiKey: string, signal?: AbortSignal): Promise<Buffer>;
263
- /** 丢掉缓存的私钥(换凭据、怀疑上游轮换私钥时调用);不给参数则全丢。 */
264
- clearPrivateKey(apiKey?: string): void;
265
- /**
266
- * 握手一次并解出私钥。
267
- *
268
- * 步骤逐字照参考实现:HKDF 导出 HMAC 密钥 → 用 `"get_sign_key\n{id}\n{ts}\n{nonce}"`
269
- * (换行分隔)算 base64 签名 → POST → 取 `data.privateCipher` → HKDF 导出 AES-GCM 密钥解密。
270
- */
271
- private performHandshake;
272
- /**
273
- * 解 `privateCipher`:base64 → iv(12) ‖ ciphertext ‖ tag(16) → AES-256-GCM。
274
- *
275
- * AAD 是 apiKeyId(逐字来自参考实现)。解密出的明文按形状判定:
276
- *
277
- * - 明文**首字节是 0x30**(ASN.1 SEQUENCE)→ 明文本身就是 PKCS#8 DER;
278
- * - 否则按参考实现的实测口径再解一层 base64(双层编码)。
279
- *
280
- * **未验证**:第一种形状没有任何证据,只是为了上游哪天改掉这层 base64 时不至于整体失败。
281
- */
282
- private decryptPrivateKey;
283
- /**
284
- * 生成本次请求的签名头表。**这是签名层唯一对外的入口,受门控。**
285
- *
286
- * 门控关闭(默认)时:返回**空表**,并且一次网络请求都不发——所以「默认路径不产生
287
- * 任何 X-Client-* 头」不是一句约定,而是这条分支的必然结果。
288
- *
289
- * 返回的表里**没有 `Authorization`**:本线路模型面的认证头由 W5/W6 装配,
290
- * Anthropic 面要求 `x-api-key` 与 `Authorization: Bearer` 双头同值(计划 §3.3),
291
- * 签名器越权写那一行会把装配层算好的头顶掉。
292
- */
293
- buildSigningHeaders(input: GlmSigningInput): Promise<GlmSigningHeaders>;
294
- }
295
- export interface GlmApplySigningOptions extends GlmClientSignerOptions {
296
- /** 复用已有签名器(跨请求复用它的握手缓存与私钥缓存)。 */
297
- signer?: GlmClientSigner;
298
- sessionId?: string;
299
- clientVersion?: string;
300
- powBits?: number;
301
- /**
302
- * 是否用 `ZCode/{version}` 覆盖调用方已有的 `User-Agent`。
303
- *
304
- * 默认 **false**:`types.ts` 的 `USER_AGENT` 明写「如实报成这个第三方插件,不冒充官方
305
- * 客户端」,开签名不必等于改身份。签名串与两个 `X-Client-Version` 头用的仍是同一个版本号,
306
- * 所以不覆盖 `User-Agent` 不会让签名失效。
307
- */
308
- overrideUserAgent?: boolean;
309
- }
310
- /**
311
- * 把签名头合并进调用方的请求头表,**就地写入并返回同一对象**。
312
- *
313
- * 门控关闭时返回原对象且**一个键都不动**——这是计划 §8.2「断言默认路径不产生 X-Client-* 头」
314
- * 对装配层(W5/W6)的保证:不调用方需要写任何 `if`。
315
- *
316
- * 合并时大小写不敏感地覆盖同名头,避免调用方已经写了 `x-client-version` 时
317
- * `fetch` 拿到两条同名头、取值取决于键的插入顺序。
318
- */
319
- export declare function applyGlmClientSigning(headers: GlmSigningHeaders, input: {
320
- apiKey: string;
321
- signal?: AbortSignal;
322
- }, options?: GlmApplySigningOptions): Promise<GlmSigningHeaders>;
323
- //# sourceMappingURL=signing.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../../../../src/host/glm-coding-plan/signing.ts"],"names":[],"mappings":"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"}