webaiapi 0.0.0-stage → 0.1.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 (205) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +184 -2
  3. package/bin/webapi.mjs +45 -0
  4. package/dist/browser/auth-capture.d.ts +110 -0
  5. package/dist/browser/auth-capture.d.ts.map +1 -0
  6. package/dist/browser/auth-capture.js +487 -0
  7. package/dist/browser/auth-capture.js.map +1 -0
  8. package/dist/browser/credentials.d.ts +102 -0
  9. package/dist/browser/credentials.d.ts.map +1 -0
  10. package/dist/browser/credentials.js +209 -0
  11. package/dist/browser/credentials.js.map +1 -0
  12. package/dist/browser/js-eval.d.ts +44 -0
  13. package/dist/browser/js-eval.d.ts.map +1 -0
  14. package/dist/browser/js-eval.js +20 -0
  15. package/dist/browser/js-eval.js.map +1 -0
  16. package/dist/browser/login-flow.d.ts +171 -0
  17. package/dist/browser/login-flow.d.ts.map +1 -0
  18. package/dist/browser/login-flow.js +606 -0
  19. package/dist/browser/login-flow.js.map +1 -0
  20. package/dist/browser/manager.d.ts +144 -0
  21. package/dist/browser/manager.d.ts.map +1 -0
  22. package/dist/browser/manager.js +586 -0
  23. package/dist/browser/manager.js.map +1 -0
  24. package/dist/browser/platforms.d.ts +96 -0
  25. package/dist/browser/platforms.d.ts.map +1 -0
  26. package/dist/browser/platforms.js +288 -0
  27. package/dist/browser/platforms.js.map +1 -0
  28. package/dist/browser/sse-capture.d.ts +23 -0
  29. package/dist/browser/sse-capture.d.ts.map +1 -0
  30. package/dist/browser/sse-capture.js +199 -0
  31. package/dist/browser/sse-capture.js.map +1 -0
  32. package/dist/browser/stealth.d.ts +12 -0
  33. package/dist/browser/stealth.d.ts.map +1 -0
  34. package/dist/browser/stealth.js +12 -0
  35. package/dist/browser/stealth.js.map +1 -0
  36. package/dist/cli.d.ts +12 -0
  37. package/dist/cli.d.ts.map +1 -0
  38. package/dist/cli.js +441 -0
  39. package/dist/cli.js.map +1 -0
  40. package/dist/config.d.ts +90 -0
  41. package/dist/config.d.ts.map +1 -0
  42. package/dist/config.js +246 -0
  43. package/dist/config.js.map +1 -0
  44. package/dist/controllers/history-db.d.ts +56 -0
  45. package/dist/controllers/history-db.d.ts.map +1 -0
  46. package/dist/controllers/history-db.js +260 -0
  47. package/dist/controllers/history-db.js.map +1 -0
  48. package/dist/controllers/request-pool.d.ts +78 -0
  49. package/dist/controllers/request-pool.d.ts.map +1 -0
  50. package/dist/controllers/request-pool.js +222 -0
  51. package/dist/controllers/request-pool.js.map +1 -0
  52. package/dist/controllers/router.d.ts +172 -0
  53. package/dist/controllers/router.d.ts.map +1 -0
  54. package/dist/controllers/router.js +569 -0
  55. package/dist/controllers/router.js.map +1 -0
  56. package/dist/index.d.ts +72 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +61 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/log/api-logger.d.ts +55 -0
  61. package/dist/log/api-logger.d.ts.map +1 -0
  62. package/dist/log/api-logger.js +264 -0
  63. package/dist/log/api-logger.js.map +1 -0
  64. package/dist/log/debug-logger.d.ts +49 -0
  65. package/dist/log/debug-logger.d.ts.map +1 -0
  66. package/dist/log/debug-logger.js +285 -0
  67. package/dist/log/debug-logger.js.map +1 -0
  68. package/dist/log/logger.d.ts +16 -0
  69. package/dist/log/logger.d.ts.map +1 -0
  70. package/dist/log/logger.js +35 -0
  71. package/dist/log/logger.js.map +1 -0
  72. package/dist/postinstall.d.ts +3 -0
  73. package/dist/postinstall.d.ts.map +1 -0
  74. package/dist/postinstall.js +90 -0
  75. package/dist/postinstall.js.map +1 -0
  76. package/dist/providers/base.d.ts +83 -0
  77. package/dist/providers/base.d.ts.map +1 -0
  78. package/dist/providers/base.js +51 -0
  79. package/dist/providers/base.js.map +1 -0
  80. package/dist/providers/chatglm-dom-extract.d.ts +24 -0
  81. package/dist/providers/chatglm-dom-extract.d.ts.map +1 -0
  82. package/dist/providers/chatglm-dom-extract.js +175 -0
  83. package/dist/providers/chatglm-dom-extract.js.map +1 -0
  84. package/dist/providers/chatglm-dom.d.ts +110 -0
  85. package/dist/providers/chatglm-dom.d.ts.map +1 -0
  86. package/dist/providers/chatglm-dom.js +384 -0
  87. package/dist/providers/chatglm-dom.js.map +1 -0
  88. package/dist/providers/chatglm-sse.d.ts +119 -0
  89. package/dist/providers/chatglm-sse.d.ts.map +1 -0
  90. package/dist/providers/chatglm-sse.js +241 -0
  91. package/dist/providers/chatglm-sse.js.map +1 -0
  92. package/dist/providers/chatglm.d.ts +288 -0
  93. package/dist/providers/chatglm.d.ts.map +1 -0
  94. package/dist/providers/chatglm.js +1631 -0
  95. package/dist/providers/chatglm.js.map +1 -0
  96. package/dist/routes/chat.d.ts +117 -0
  97. package/dist/routes/chat.d.ts.map +1 -0
  98. package/dist/routes/chat.js +1346 -0
  99. package/dist/routes/chat.js.map +1 -0
  100. package/dist/routes/compress.d.ts +142 -0
  101. package/dist/routes/compress.d.ts.map +1 -0
  102. package/dist/routes/compress.js +551 -0
  103. package/dist/routes/compress.js.map +1 -0
  104. package/dist/routes/failover.d.ts +34 -0
  105. package/dist/routes/failover.d.ts.map +1 -0
  106. package/dist/routes/failover.js +221 -0
  107. package/dist/routes/failover.js.map +1 -0
  108. package/dist/routes/helpers.d.ts +174 -0
  109. package/dist/routes/helpers.d.ts.map +1 -0
  110. package/dist/routes/helpers.js +525 -0
  111. package/dist/routes/helpers.js.map +1 -0
  112. package/dist/routes/meta.d.ts +31 -0
  113. package/dist/routes/meta.d.ts.map +1 -0
  114. package/dist/routes/meta.js +184 -0
  115. package/dist/routes/meta.js.map +1 -0
  116. package/dist/routes/sse.d.ts +82 -0
  117. package/dist/routes/sse.d.ts.map +1 -0
  118. package/dist/routes/sse.js +77 -0
  119. package/dist/routes/sse.js.map +1 -0
  120. package/dist/server/app.d.ts +24 -0
  121. package/dist/server/app.d.ts.map +1 -0
  122. package/dist/server/app.js +292 -0
  123. package/dist/server/app.js.map +1 -0
  124. package/dist/server/middleware/api-key.d.ts +61 -0
  125. package/dist/server/middleware/api-key.d.ts.map +1 -0
  126. package/dist/server/middleware/api-key.js +95 -0
  127. package/dist/server/middleware/api-key.js.map +1 -0
  128. package/dist/server/middleware/rate-limit.d.ts +67 -0
  129. package/dist/server/middleware/rate-limit.d.ts.map +1 -0
  130. package/dist/server/middleware/rate-limit.js +134 -0
  131. package/dist/server/middleware/rate-limit.js.map +1 -0
  132. package/dist/server/middleware/timeout.d.ts +34 -0
  133. package/dist/server/middleware/timeout.d.ts.map +1 -0
  134. package/dist/server/middleware/timeout.js +64 -0
  135. package/dist/server/middleware/timeout.js.map +1 -0
  136. package/dist/server/types.d.ts +20 -0
  137. package/dist/server/types.d.ts.map +1 -0
  138. package/dist/server/types.js +2 -0
  139. package/dist/server/types.js.map +1 -0
  140. package/dist/tools/build.d.ts +14 -0
  141. package/dist/tools/build.d.ts.map +1 -0
  142. package/dist/tools/build.js +105 -0
  143. package/dist/tools/build.js.map +1 -0
  144. package/dist/tools/clean.d.ts +32 -0
  145. package/dist/tools/clean.d.ts.map +1 -0
  146. package/dist/tools/clean.js +65 -0
  147. package/dist/tools/clean.js.map +1 -0
  148. package/dist/tools/convert.d.ts +50 -0
  149. package/dist/tools/convert.d.ts.map +1 -0
  150. package/dist/tools/convert.js +289 -0
  151. package/dist/tools/convert.js.map +1 -0
  152. package/dist/tools/names.d.ts +138 -0
  153. package/dist/tools/names.d.ts.map +1 -0
  154. package/dist/tools/names.js +578 -0
  155. package/dist/tools/names.js.map +1 -0
  156. package/dist/tools/parse.d.ts +31 -0
  157. package/dist/tools/parse.d.ts.map +1 -0
  158. package/dist/tools/parse.js +273 -0
  159. package/dist/tools/parse.js.map +1 -0
  160. package/dist/tools/placeholder.d.ts +21 -0
  161. package/dist/tools/placeholder.d.ts.map +1 -0
  162. package/dist/tools/placeholder.js +135 -0
  163. package/dist/tools/placeholder.js.map +1 -0
  164. package/dist/tools/prompts.d.ts +42 -0
  165. package/dist/tools/prompts.d.ts.map +1 -0
  166. package/dist/tools/prompts.js +69 -0
  167. package/dist/tools/prompts.js.map +1 -0
  168. package/dist/tools/protocol.d.ts +58 -0
  169. package/dist/tools/protocol.d.ts.map +1 -0
  170. package/dist/tools/protocol.js +287 -0
  171. package/dist/tools/protocol.js.map +1 -0
  172. package/dist/tools/repair.d.ts +83 -0
  173. package/dist/tools/repair.d.ts.map +1 -0
  174. package/dist/tools/repair.js +510 -0
  175. package/dist/tools/repair.js.map +1 -0
  176. package/dist/tools/workspace.d.ts +40 -0
  177. package/dist/tools/workspace.d.ts.map +1 -0
  178. package/dist/tools/workspace.js +224 -0
  179. package/dist/tools/workspace.js.map +1 -0
  180. package/dist/types/message.d.ts +87 -0
  181. package/dist/types/message.d.ts.map +1 -0
  182. package/dist/types/message.js +85 -0
  183. package/dist/types/message.js.map +1 -0
  184. package/dist/types/openai.d.ts +100 -0
  185. package/dist/types/openai.d.ts.map +1 -0
  186. package/dist/types/openai.js +66 -0
  187. package/dist/types/openai.js.map +1 -0
  188. package/dist/utils/errors.d.ts +82 -0
  189. package/dist/utils/errors.d.ts.map +1 -0
  190. package/dist/utils/errors.js +115 -0
  191. package/dist/utils/errors.js.map +1 -0
  192. package/dist/utils/mutex.d.ts +31 -0
  193. package/dist/utils/mutex.d.ts.map +1 -0
  194. package/dist/utils/mutex.js +61 -0
  195. package/dist/utils/mutex.js.map +1 -0
  196. package/dist/utils/prompt.d.ts +150 -0
  197. package/dist/utils/prompt.d.ts.map +1 -0
  198. package/dist/utils/prompt.js +514 -0
  199. package/dist/utils/prompt.js.map +1 -0
  200. package/dist/utils/text.d.ts +30 -0
  201. package/dist/utils/text.d.ts.map +1 -0
  202. package/dist/utils/text.js +70 -0
  203. package/dist/utils/text.js.map +1 -0
  204. package/package.json +67 -4
  205. package/postinstall.mjs +34 -0
@@ -0,0 +1,209 @@
1
+ /**
2
+ * 凭证读取 —— `legacy-python/src/browser/cdp_capture.py` 中**运行时用到**的那部分。
3
+ *
4
+ * 拆出本模块的原因:凭证路径/格式是 `manager`(注入 Cookie)、`router`(挑账号、判身份)
5
+ * 与 CLI(登录并保存)三处共用的;Python 版把它们散在 `cdp_capture.py`(1,040 行)里,
6
+ * 而那个文件大部分是**只在登录流程用**的 `AuthCapture` 类。
7
+ *
8
+ * 只移植运行时需要的:路径解析、`loadAuth`、`listAccounts`、`isAuthAvailable`、
9
+ * JWT/Cookie 身份提取。
10
+ * ⬜ **登录捕获流程(`AuthCapture` / `capturePlatformAuth`)推迟到 M5**(只被 CLI 使用)。
11
+ *
12
+ * ⚠️ 与 Python 版的差异:Python 的 `load_auth()` 把目录写死成 `~/.ai-api/auth`,
13
+ * 而 `settings.auth_dir` 配置项形同虚设。这里统一走 `settings.authDir`
14
+ * (默认值就是 `~/.ai-api/auth`,所以实际行为一致,但配置项从此真的生效)。
15
+ */
16
+ import { createHash } from 'node:crypto';
17
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
18
+ import { join } from 'node:path';
19
+ import { expandHome, settings } from '../config.js';
20
+ import { logger } from '../log/logger.js';
21
+ /* ------------------------------------------------------------------ */
22
+ /* 路径 */
23
+ /* ------------------------------------------------------------------ */
24
+ /** 凭证根目录(`~/.ai-api/auth`)。 */
25
+ export function authBaseDir(authDir) {
26
+ return expandHome(authDir ?? settings.authDir ?? '~/.ai-api/auth');
27
+ }
28
+ /** 某账号的凭证文件路径(新格式 `{base}/{platform}/{account}.json`)。 */
29
+ export function authFilePath(platform, accountId = 'default', authDir) {
30
+ return join(authBaseDir(authDir), platform, `${accountId}.json`);
31
+ }
32
+ /** 旧格式单文件路径(`{base}/{platform}.json`)。 */
33
+ export function legacyAuthFilePath(platform, authDir) {
34
+ return join(authBaseDir(authDir), `${platform}.json`);
35
+ }
36
+ /* ------------------------------------------------------------------ */
37
+ /* 读取 */
38
+ /* ------------------------------------------------------------------ */
39
+ /**
40
+ * 加载某账号的凭证;不存在或没有 cookies 时返回 `null`。
41
+ *
42
+ * ⚠️ **必须真的检查 cookies**:Python 版这里曾经整段读取/校验逻辑丢失,
43
+ * 函数体退化成「打开文件 → 打一条 warning → 返回 None」,
44
+ * 导致 `load_auth()` 永远返回 None,登录检查全部误报「凭证缺少 cookies」。
45
+ * 这个校验不能再丢。
46
+ */
47
+ export function loadAuth(platform, options = {}) {
48
+ const { accountId = 'default', authDir } = options;
49
+ let file = authFilePath(platform, accountId, authDir);
50
+ if (!existsSync(file)) {
51
+ // 向后兼容:旧格式单文件(仅 default 账号)
52
+ const legacy = legacyAuthFilePath(platform, authDir);
53
+ if (accountId === 'default' && existsSync(legacy)) {
54
+ file = legacy;
55
+ }
56
+ else {
57
+ return null;
58
+ }
59
+ }
60
+ try {
61
+ const auth = JSON.parse(readFileSync(file, 'utf8'));
62
+ const cookies = auth.cookies ?? [];
63
+ if (cookies.length === 0) {
64
+ logger.warn(`[credentials] ${platform}/${accountId} 凭证缺少 cookies`);
65
+ return null;
66
+ }
67
+ auth._account_id = accountId;
68
+ return auth;
69
+ }
70
+ catch (error) {
71
+ logger.error(`[credentials] 加载 ${platform}/${accountId} 凭证失败: ${String(error)}`);
72
+ return null;
73
+ }
74
+ }
75
+ /**
76
+ * 列出某平台已捕获的账号 ID。
77
+ *
78
+ * 会跳过捕获过程中的临时文件(`__tmp__<ts>.json` / `__new__*`)——
79
+ * 崩溃残留不是真实账号。
80
+ */
81
+ export function listAccounts(platform, authDir) {
82
+ const platformDir = join(authBaseDir(authDir), platform);
83
+ const accounts = [];
84
+ if (existsSync(platformDir)) {
85
+ for (const entry of readdirSync(platformDir)) {
86
+ if (!entry.endsWith('.json'))
87
+ continue;
88
+ const stem = entry.slice(0, -'.json'.length);
89
+ if (stem.startsWith('__tmp__') || stem.startsWith('__new__'))
90
+ continue;
91
+ accounts.push(stem);
92
+ }
93
+ }
94
+ // 向后兼容:旧格式单文件
95
+ if (accounts.length === 0 && existsSync(legacyAuthFilePath(platform, authDir))) {
96
+ accounts.push('default');
97
+ }
98
+ return accounts.sort();
99
+ }
100
+ /** 指定平台/账号是否有可用凭证。 */
101
+ export function isAuthAvailable(platform, options = {}) {
102
+ return loadAuth(platform, options) !== null;
103
+ }
104
+ /* ------------------------------------------------------------------ */
105
+ /* 身份提取 */
106
+ /* ------------------------------------------------------------------ */
107
+ /** 解码 JWT payload(不验签,仅用于读用户标识)。 */
108
+ export function decodeJwt(token) {
109
+ if (!token)
110
+ return {};
111
+ const raw = token.startsWith('Bearer ') ? token.slice(7) : token;
112
+ const parts = raw.split('.');
113
+ if (parts.length !== 3)
114
+ return {};
115
+ try {
116
+ let payload = parts[1];
117
+ // 补齐 base64 padding
118
+ payload += '='.repeat((4 - (payload.length % 4)) % 4);
119
+ const decoded = Buffer.from(payload.replace(/-/g, '+').replace(/_/g, '/'), 'base64').toString('utf8');
120
+ const parsed = JSON.parse(decoded);
121
+ return parsed && typeof parsed === 'object' ? parsed : {};
122
+ }
123
+ catch (error) {
124
+ logger.debug(`[credentials] JWT 解码失败: ${String(error)}`);
125
+ return {};
126
+ }
127
+ }
128
+ /** 从 cookie 列表里取指定名称的值。 */
129
+ export function getCookieValue(cookies, name) {
130
+ for (const c of cookies ?? []) {
131
+ if (c?.name === name)
132
+ return c.value;
133
+ }
134
+ return undefined;
135
+ }
136
+ /*
137
+ * ⬜ `extractAccountInfoSync` 已**迁到 `platforms.ts`**:
138
+ * 它按平台名分支,属于「平台元数据」而不是「凭证读写」。
139
+ * 留在这里会造成 `credentials ⇄ platforms` 循环 import。
140
+ * 需要它请从 `./platforms.js` 引入。
141
+ */
142
+ /**
143
+ * 计算 Cookie 指纹(用于判断「两份凭证是不是同一个会话」)。
144
+ *
145
+ * 用途:`ModelRouter` 启用辅助通道前的三重校验之一。
146
+ * 实测踩坑:把 `default.json` 复制成 `acc2.json` 后,账号数变成 2,
147
+ * 但其实是同一个人的登录态 → 辅助通道「并行」时立刻撞
148
+ * 「请等待其他对话生成完毕」。只看账号数看不出来,必须比 Cookie 值。
149
+ *
150
+ * 用 Node 内置 crypto,返回稳定的十六进制摘要。
151
+ */
152
+ export function cookieFingerprint(cookies) {
153
+ const pairs = (cookies ?? [])
154
+ .filter((c) => c && typeof c.name === 'string')
155
+ .map((c) => `${c.name}=${c.value ?? ''}`)
156
+ .sort();
157
+ return createHash('sha256').update(pairs.join(';')).digest('hex').slice(0, 32);
158
+ }
159
+ /**
160
+ * 把抓到的 cookie 规范成 Playwright `addCookies` 能接受的形态。
161
+ *
162
+ * 为什么需要:Playwright 会校验 `sameSite`(只认 Strict/Lax/None)与
163
+ * `expires`(必须是数值)。从 cookie jar / 扩展导出的数据里常见
164
+ * `"no_restriction"` / `"unspecified"` 这类字面量,直接透传会**抛异常**导致
165
+ * 整批 Cookie 注入失败(表现为「莫名其妙未登录」)。
166
+ * Python 版直接透传,因为它的数据源恰好都是合规的 —— 这里做一层兜底。
167
+ */
168
+ export function normalizeCookies(cookies) {
169
+ const out = [];
170
+ for (const c of cookies ?? []) {
171
+ if (!c || typeof c.name !== 'string' || typeof c.value !== 'string')
172
+ continue;
173
+ const cookie = { name: c.name, value: c.value };
174
+ if (typeof c.domain === 'string')
175
+ cookie.domain = c.domain;
176
+ if (typeof c.path === 'string')
177
+ cookie.path = c.path;
178
+ if (typeof c.url === 'string')
179
+ cookie.url = c.url;
180
+ if (typeof c.expires === 'number' && Number.isFinite(c.expires))
181
+ cookie.expires = c.expires;
182
+ if (typeof c.httpOnly === 'boolean')
183
+ cookie.httpOnly = c.httpOnly;
184
+ if (typeof c.secure === 'boolean')
185
+ cookie.secure = c.secure;
186
+ if (typeof c.sameSite === 'string') {
187
+ const mapped = mapSameSite(c.sameSite);
188
+ if (mapped)
189
+ cookie.sameSite = mapped;
190
+ }
191
+ out.push(cookie);
192
+ }
193
+ return out;
194
+ }
195
+ function mapSameSite(raw) {
196
+ switch (raw.trim().toLowerCase()) {
197
+ case 'strict':
198
+ return 'Strict';
199
+ case 'lax':
200
+ return 'Lax';
201
+ case 'none':
202
+ case 'no_restriction':
203
+ return 'None';
204
+ default:
205
+ // 'unspecified' 等无法映射的值直接丢弃该字段(用浏览器默认)
206
+ return undefined;
207
+ }
208
+ }
209
+ //# sourceMappingURL=credentials.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/browser/credentials.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * 页面脚本求值辅助。
3
+ *
4
+ * ## ⚠️⚠️ 存在的唯一理由:Playwright Node 与 Python 的一处**不兼容**
5
+ *
6
+ * `page.evaluate(x)` 的语义在两个语言里不一样:
7
+ *
8
+ * | 传入 | Python | Node |
9
+ * |---|---|---|
10
+ * | `"() => ({a:1})"` | **自动调用**该函数 → `{a:1}` | 当作**表达式**求值 → **`undefined`** |
11
+ * | `"(() => ({a:1}))()"` | `{a:1}` | `{a:1}` ✅ |
12
+ * | `() => ({a:1})`(真函数) | `{a:1}` | `{a:1}` ✅ |
13
+ *
14
+ * 实测(Playwright 1.64 / Node 24):
15
+ * ```
16
+ * evaluate('() => ({a: 1})') -> undefined
17
+ * evaluate('(() => ({a: 1}))()') -> {"a":1}
18
+ * evaluate(() => ({a: 1})) -> {"a":1}
19
+ * ```
20
+ *
21
+ * 这是从 Python 移植时**最危险的一个陷阱**:整条链路上所有 DOM/SSE 操作都会
22
+ * 静默拿到 `undefined`,**不抛异常、不打日志**。表现是「服务起来了、
23
+ * 请求也返回 200,但永远没有正文 / 永远探测不出登录态」——
24
+ * 排查时几乎不可能想到是「函数没被调用」。
25
+ *
26
+ * 因此本文件强制:**凡是要在页面里执行的函数表达式,都必须经 {@link iife} 包装**。
27
+ */
28
+ import type { Page } from 'playwright';
29
+ /**
30
+ * 把「函数表达式字符串」包装成可求值的 IIFE 表达式。
31
+ *
32
+ * 输入 `() => { return 1; }` → 输出 `(() => { return 1; })()`。
33
+ *
34
+ * ⚠️ 必须保留外层括号:箭头函数直接加 `()` 在 `=>` 与 `{` 之间会被解析错
35
+ * (`() => {}()` 会被当成「返回 undefined 的函数」而不是「调用」)。
36
+ */
37
+ export declare function iife(expression: string): string;
38
+ /**
39
+ * 在页面里执行函数表达式并取回结果。
40
+ *
41
+ * 语义等价于 Python 的 `page.evaluate("() => {...}")`。
42
+ */
43
+ export declare function evaluateFn<T>(page: Page, fnExpression: string): Promise<T>;
44
+ //# sourceMappingURL=js-eval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"js-eval.d.ts","sourceRoot":"","sources":["../../src/browser/js-eval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAE1E"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * 把「函数表达式字符串」包装成可求值的 IIFE 表达式。
3
+ *
4
+ * 输入 `() => { return 1; }` → 输出 `(() => { return 1; })()`。
5
+ *
6
+ * ⚠️ 必须保留外层括号:箭头函数直接加 `()` 在 `=>` 与 `{` 之间会被解析错
7
+ * (`() => {}()` 会被当成「返回 undefined 的函数」而不是「调用」)。
8
+ */
9
+ export function iife(expression) {
10
+ return `(${expression})()`;
11
+ }
12
+ /**
13
+ * 在页面里执行函数表达式并取回结果。
14
+ *
15
+ * 语义等价于 Python 的 `page.evaluate("() => {...}")`。
16
+ */
17
+ export function evaluateFn(page, fnExpression) {
18
+ return page.evaluate(iife(fnExpression));
19
+ }
20
+ //# sourceMappingURL=js-eval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"js-eval.js","sourceRoot":"","sources":["../../src/browser/js-eval.ts"],"names":[],"mappings":"AA6BA;;;;;;;GAOG;AACH,MAAM,UAAU,IAAI,CAAC,UAAkB;IACrC,OAAO,IAAI,UAAU,KAAK,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAI,IAAU,EAAE,YAAoB;IAC5D,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAe,CAAC;AACzD,CAAC"}
@@ -0,0 +1,171 @@
1
+ import { type Choice } from '../utils/prompt.js';
2
+ /** 判断「是不是同一个人 / 同一个登录态」所需的最小信息集。 */
3
+ export interface IdentityPrint {
4
+ /** 平台内的稳定身份标识(`extractAccountInfoSync` 的 `identifier`)。 */
5
+ identity: string;
6
+ /** 人类可读标签(用户名 / 邮箱)。 */
7
+ label: string;
8
+ /** Cookie 指纹({@link cookieFingerprint})。 */
9
+ fingerprint: string;
10
+ /** Cookie 数量(用来判断指纹是不是「空集指纹」)。 */
11
+ cookies: number;
12
+ }
13
+ /** 磁盘上已有的账号。 */
14
+ export interface ExistingAccount extends IdentityPrint {
15
+ id: string;
16
+ capturedAt: number;
17
+ }
18
+ /** 对「新捕获的凭证」与「已有账号」关系的判定。 */
19
+ export type DuplicateVerdict =
20
+ /** 全新账号。 */
21
+ {
22
+ kind: 'fresh';
23
+ }
24
+ /** Cookie 完全一致 —— **同一个登录态**(同一个人的同一份会话)。 */
25
+ | {
26
+ kind: 'same-session';
27
+ accountId: string;
28
+ }
29
+ /** 身份一致但 Cookie 不同 —— **同一个人重新登录**(如 cookie 过期后重登)。 */
30
+ | {
31
+ kind: 'same-identity';
32
+ accountId: string;
33
+ };
34
+ /**
35
+ * 判断新捕获的凭证和已有账号是不是同一个人。
36
+ *
37
+ * 判定顺序(**先指纹后身份**,强度递减):
38
+ * 1. Cookie 指纹完全相同 → `same-session`。这比身份更硬:身份标识可能因为
39
+ * 平台改字段而提取不到,但 Cookie 值对了就是同一份会话。
40
+ * 2. 身份标识(`identifier`)相同 → `same-identity`。同一个人换了会话
41
+ * (重登、cookie 轮换)。
42
+ *
43
+ * ⚠️ `identity` 是 `'unknown'` 时**不算匹配**:兜底值对所有提取失败的平台都一样,
44
+ * 拿它比对会把两个毫不相干的账号判成同一个人,反而制造出「并行打同一个账号」
45
+ * 那个它本该防止的问题。
46
+ *
47
+ * ⚠️ 指纹比对要求 `cookies > 0`:空 Cookie 列表的指纹是个常量,
48
+ * 两个「没抓到 cookie」的凭证会互相匹配。
49
+ */
50
+ export declare function detectDuplicate(captured: IdentityPrint, existing: ReadonlyArray<ExistingAccount>): DuplicateVerdict;
51
+ /**
52
+ * 把任意字符串(用户名 / uid / 用户输入)洗成能当文件名的形式。
53
+ *
54
+ * 规则:非 `[A-Za-z0-9._-]` 的字符全部折成 `-`,合并连续分隔符、去掉首尾分隔符、
55
+ * 转小写、截断到 32 字符。
56
+ *
57
+ * ⚠️ 洗不出东西时返回**空串**(而不是兜底成某个词):中文用户名就属于这种,
58
+ * 调用方需要知道「这个候选废了」才能退到下一个候选(见 {@link deriveAccountId})。
59
+ *
60
+ * ⚠️ 返回值一定满足 `^[A-Za-z0-9._-]*$` 且不含 `/` —— 账号 ID 会被当作文件名
61
+ * 拼接,这是防路径穿越的第一道闸(`AuthCapture.saveAs` 还有第二道硬校验)。
62
+ */
63
+ export declare function toSlug(raw: string): string;
64
+ /**
65
+ * 洗成**唯一**的账号 ID,可直接当文件名。
66
+ *
67
+ * ⚠️ **必须去重**:`existing` 里已有的名字要避开(`alice` → `alice-2`)。
68
+ * 否则第二次登录同一个平台会把第一个账号的文件**原地覆盖**。
69
+ */
70
+ export declare function slugAccountId(raw: string, existing?: readonly string[]): string;
71
+ /**
72
+ * 按优先级给账号挑一个名字。
73
+ *
74
+ * 顺序:用户显式给的 → 身份标签(用户名)→ 身份标识(uid)→ `account`。
75
+ * 逐个尝试而不是只用第一个,是因为中文用户名洗完是空串,
76
+ * 那时应该退到 uid,而不是直接落到无意义的 `account`。
77
+ */
78
+ export declare function deriveAccountId(candidates: ReadonlyArray<string | undefined>, existing?: readonly string[]): string;
79
+ /**
80
+ * 读出某平台已有的全部账号(含身份与指纹)。
81
+ *
82
+ * ⚠️ **只返回「能用的」账号**:`loadAuth` 会挡掉没有 cookie 或 JSON 损坏的文件,
83
+ * 而那些文件不应该参与「这是不是同一个人」的判断(它们根本没会话可比)。
84
+ * 需要**列出全部文件**(用来删除)请用 `listAccounts`。
85
+ *
86
+ * @param authDir 凭证目录(默认 `settings.authDir`,测试时传临时目录)
87
+ */
88
+ export declare function readExistingAccounts(platform: string, authDir?: string): ExistingAccount[];
89
+ /**
90
+ * `login` 的动作菜单(纯函数,可单测)。
91
+ *
92
+ * ⚠️ 最后一项是**导航项**(`Symbol`),不是账号 ID —— 抽成纯函数就是为了让
93
+ * 「`canGoBack` 时给返回、否则给取消」这条规则能被测试钉住:它是唯一
94
+ * 决定「用户能不能退回去」的地方,改了没有任何别的东西会报错。
95
+ *
96
+ * @param canGoBack 平台是**从菜单选的**才为 true(命令行给的平台没有上一步)
97
+ */
98
+ export declare function buildLoginActionChoices(existing: ReadonlyArray<ExistingAccount>, options: {
99
+ canGoBack: boolean;
100
+ }): Choice<string | NavChoice>[];
101
+ export interface LoginOptions {
102
+ /** `webapi login <platform>`;缺省时交互选择。 */
103
+ platform?: string;
104
+ /** `--account <id>`:跳过「存成哪个账号」的询问。 */
105
+ account?: string;
106
+ /** `--yes`:所有确认直接通过(脚本用)。 */
107
+ yes?: boolean;
108
+ /** `--no-input`:即使有 TTY 也走非交互路径。 */
109
+ noInput?: boolean;
110
+ }
111
+ /**
112
+ * 菜单里的「返回上一步」哨兵。
113
+ *
114
+ * ⚠️ 用 `Symbol` 而不是 `'__back__'` 这类字符串:菜单选项的值里混着
115
+ * **真实账号 ID**,总有一天会和某个账号名撞上 —— 而且不会报错,
116
+ * 只表现为「选那个账号时莫名回到了上一步」。
117
+ */
118
+ declare const BACK: unique symbol;
119
+ /** 菜单里的「退出 / 取消」哨兵(与 {@link BACK} 区分:一个是回上一步,一个是结束)。 */
120
+ declare const ABORT: unique symbol;
121
+ /** 导航选项的类型。 */
122
+ type NavChoice = typeof BACK | typeof ABORT;
123
+ /**
124
+ * `webapi login` 的完整流程。
125
+ *
126
+ * ## 导航模型
127
+ * 交互式登录是**两级**的(选平台 → 选动作),所以用一个小循环 + 显式哨兵
128
+ * 而不是一串顺序执行的 `if`:
129
+ *
130
+ * ```
131
+ * 平台菜单 ──选平台──▶ 动作菜单 ──选动作──▶ 开始捕获
132
+ * ▲ │
133
+ * └──── 「← 返回上一步」─┘
134
+ * ```
135
+ *
136
+ * ⚠️ **只从平台菜单进来的才有「上一步」**:`webapi login chatglm` 是用户在命令行
137
+ * 明确指定的平台,没有可返回的地方,那里给的是「✗ 取消」。
138
+ *
139
+ * ⚠️ 动作菜单**即使 0 个账号也照样显示**(此时只有「添加新账号」+ 返回/取消)。
140
+ * 看起来多按一次回车,换来的是「开了浏览器才发现平台选错」时还能退出来
141
+ * —— 浏览器一旦启动就得等它登录完或 Ctrl+C。
142
+ *
143
+ * @returns 退出码:0 成功 / 1 失败 / 130 用户取消
144
+ */
145
+ export declare function runLogin(options?: LoginOptions): Promise<number>;
146
+ export interface LogoutOptions {
147
+ /** `webapi logout <platform>`;缺省时交互选择。 */
148
+ platform?: string;
149
+ /** `--account <id>`:跳过账号询问。 */
150
+ account?: string;
151
+ /** `--yes`:跳过删除确认(脚本用,**非交互环境必需**)。 */
152
+ yes?: boolean;
153
+ /** `--no-input`:即使有 TTY 也走非交互路径。 */
154
+ noInput?: boolean;
155
+ }
156
+ /**
157
+ * `webapi logout` 的完整流程。
158
+ *
159
+ * ## ⚠️ 这里修掉了一个**会静默删错文件**的老问题
160
+ * 旧实现是 `webapi logout <platform> [--account x]`,`account` 缺省值写死为
161
+ * `'default'`。于是 `webapi logout chatglm`(本意可能只是「看看怎么用」)
162
+ * **直接把 default 账号的凭证删掉了**,而且只在 stdout 说一句「已删除」。
163
+ *
164
+ * 现在:账号必须**显式给出**(`--account`)或**从菜单里选**;
165
+ * 非交互且没给 `--account` 时**直接报错退出**,绝不替用户猜。
166
+ *
167
+ * @returns 退出码:0 成功 / 1 失败或未确认 / 130 用户取消
168
+ */
169
+ export declare function runLogout(options?: LogoutOptions): Promise<number>;
170
+ export {};
171
+ //# sourceMappingURL=login-flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-flow.d.ts","sourceRoot":"","sources":["../../src/browser/login-flow.ts"],"names":[],"mappings":"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"}