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.
- package/LICENSE +21 -0
- package/README.md +184 -2
- package/bin/webapi.mjs +45 -0
- package/dist/browser/auth-capture.d.ts +110 -0
- package/dist/browser/auth-capture.d.ts.map +1 -0
- package/dist/browser/auth-capture.js +487 -0
- package/dist/browser/auth-capture.js.map +1 -0
- package/dist/browser/credentials.d.ts +102 -0
- package/dist/browser/credentials.d.ts.map +1 -0
- package/dist/browser/credentials.js +209 -0
- package/dist/browser/credentials.js.map +1 -0
- package/dist/browser/js-eval.d.ts +44 -0
- package/dist/browser/js-eval.d.ts.map +1 -0
- package/dist/browser/js-eval.js +20 -0
- package/dist/browser/js-eval.js.map +1 -0
- package/dist/browser/login-flow.d.ts +171 -0
- package/dist/browser/login-flow.d.ts.map +1 -0
- package/dist/browser/login-flow.js +606 -0
- package/dist/browser/login-flow.js.map +1 -0
- package/dist/browser/manager.d.ts +144 -0
- package/dist/browser/manager.d.ts.map +1 -0
- package/dist/browser/manager.js +586 -0
- package/dist/browser/manager.js.map +1 -0
- package/dist/browser/platforms.d.ts +96 -0
- package/dist/browser/platforms.d.ts.map +1 -0
- package/dist/browser/platforms.js +288 -0
- package/dist/browser/platforms.js.map +1 -0
- package/dist/browser/sse-capture.d.ts +23 -0
- package/dist/browser/sse-capture.d.ts.map +1 -0
- package/dist/browser/sse-capture.js +199 -0
- package/dist/browser/sse-capture.js.map +1 -0
- package/dist/browser/stealth.d.ts +12 -0
- package/dist/browser/stealth.d.ts.map +1 -0
- package/dist/browser/stealth.js +12 -0
- package/dist/browser/stealth.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +441 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +90 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +246 -0
- package/dist/config.js.map +1 -0
- package/dist/controllers/history-db.d.ts +56 -0
- package/dist/controllers/history-db.d.ts.map +1 -0
- package/dist/controllers/history-db.js +260 -0
- package/dist/controllers/history-db.js.map +1 -0
- package/dist/controllers/request-pool.d.ts +78 -0
- package/dist/controllers/request-pool.d.ts.map +1 -0
- package/dist/controllers/request-pool.js +222 -0
- package/dist/controllers/request-pool.js.map +1 -0
- package/dist/controllers/router.d.ts +172 -0
- package/dist/controllers/router.d.ts.map +1 -0
- package/dist/controllers/router.js +569 -0
- package/dist/controllers/router.js.map +1 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/log/api-logger.d.ts +55 -0
- package/dist/log/api-logger.d.ts.map +1 -0
- package/dist/log/api-logger.js +264 -0
- package/dist/log/api-logger.js.map +1 -0
- package/dist/log/debug-logger.d.ts +49 -0
- package/dist/log/debug-logger.d.ts.map +1 -0
- package/dist/log/debug-logger.js +285 -0
- package/dist/log/debug-logger.js.map +1 -0
- package/dist/log/logger.d.ts +16 -0
- package/dist/log/logger.d.ts.map +1 -0
- package/dist/log/logger.js +35 -0
- package/dist/log/logger.js.map +1 -0
- package/dist/postinstall.d.ts +3 -0
- package/dist/postinstall.d.ts.map +1 -0
- package/dist/postinstall.js +90 -0
- package/dist/postinstall.js.map +1 -0
- package/dist/providers/base.d.ts +83 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +51 -0
- package/dist/providers/base.js.map +1 -0
- package/dist/providers/chatglm-dom-extract.d.ts +24 -0
- package/dist/providers/chatglm-dom-extract.d.ts.map +1 -0
- package/dist/providers/chatglm-dom-extract.js +175 -0
- package/dist/providers/chatglm-dom-extract.js.map +1 -0
- package/dist/providers/chatglm-dom.d.ts +110 -0
- package/dist/providers/chatglm-dom.d.ts.map +1 -0
- package/dist/providers/chatglm-dom.js +384 -0
- package/dist/providers/chatglm-dom.js.map +1 -0
- package/dist/providers/chatglm-sse.d.ts +119 -0
- package/dist/providers/chatglm-sse.d.ts.map +1 -0
- package/dist/providers/chatglm-sse.js +241 -0
- package/dist/providers/chatglm-sse.js.map +1 -0
- package/dist/providers/chatglm.d.ts +288 -0
- package/dist/providers/chatglm.d.ts.map +1 -0
- package/dist/providers/chatglm.js +1631 -0
- package/dist/providers/chatglm.js.map +1 -0
- package/dist/routes/chat.d.ts +117 -0
- package/dist/routes/chat.d.ts.map +1 -0
- package/dist/routes/chat.js +1346 -0
- package/dist/routes/chat.js.map +1 -0
- package/dist/routes/compress.d.ts +142 -0
- package/dist/routes/compress.d.ts.map +1 -0
- package/dist/routes/compress.js +551 -0
- package/dist/routes/compress.js.map +1 -0
- package/dist/routes/failover.d.ts +34 -0
- package/dist/routes/failover.d.ts.map +1 -0
- package/dist/routes/failover.js +221 -0
- package/dist/routes/failover.js.map +1 -0
- package/dist/routes/helpers.d.ts +174 -0
- package/dist/routes/helpers.d.ts.map +1 -0
- package/dist/routes/helpers.js +525 -0
- package/dist/routes/helpers.js.map +1 -0
- package/dist/routes/meta.d.ts +31 -0
- package/dist/routes/meta.d.ts.map +1 -0
- package/dist/routes/meta.js +184 -0
- package/dist/routes/meta.js.map +1 -0
- package/dist/routes/sse.d.ts +82 -0
- package/dist/routes/sse.d.ts.map +1 -0
- package/dist/routes/sse.js +77 -0
- package/dist/routes/sse.js.map +1 -0
- package/dist/server/app.d.ts +24 -0
- package/dist/server/app.d.ts.map +1 -0
- package/dist/server/app.js +292 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/middleware/api-key.d.ts +61 -0
- package/dist/server/middleware/api-key.d.ts.map +1 -0
- package/dist/server/middleware/api-key.js +95 -0
- package/dist/server/middleware/api-key.js.map +1 -0
- package/dist/server/middleware/rate-limit.d.ts +67 -0
- package/dist/server/middleware/rate-limit.d.ts.map +1 -0
- package/dist/server/middleware/rate-limit.js +134 -0
- package/dist/server/middleware/rate-limit.js.map +1 -0
- package/dist/server/middleware/timeout.d.ts +34 -0
- package/dist/server/middleware/timeout.d.ts.map +1 -0
- package/dist/server/middleware/timeout.js +64 -0
- package/dist/server/middleware/timeout.js.map +1 -0
- package/dist/server/types.d.ts +20 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +2 -0
- package/dist/server/types.js.map +1 -0
- package/dist/tools/build.d.ts +14 -0
- package/dist/tools/build.d.ts.map +1 -0
- package/dist/tools/build.js +105 -0
- package/dist/tools/build.js.map +1 -0
- package/dist/tools/clean.d.ts +32 -0
- package/dist/tools/clean.d.ts.map +1 -0
- package/dist/tools/clean.js +65 -0
- package/dist/tools/clean.js.map +1 -0
- package/dist/tools/convert.d.ts +50 -0
- package/dist/tools/convert.d.ts.map +1 -0
- package/dist/tools/convert.js +289 -0
- package/dist/tools/convert.js.map +1 -0
- package/dist/tools/names.d.ts +138 -0
- package/dist/tools/names.d.ts.map +1 -0
- package/dist/tools/names.js +578 -0
- package/dist/tools/names.js.map +1 -0
- package/dist/tools/parse.d.ts +31 -0
- package/dist/tools/parse.d.ts.map +1 -0
- package/dist/tools/parse.js +273 -0
- package/dist/tools/parse.js.map +1 -0
- package/dist/tools/placeholder.d.ts +21 -0
- package/dist/tools/placeholder.d.ts.map +1 -0
- package/dist/tools/placeholder.js +135 -0
- package/dist/tools/placeholder.js.map +1 -0
- package/dist/tools/prompts.d.ts +42 -0
- package/dist/tools/prompts.d.ts.map +1 -0
- package/dist/tools/prompts.js +69 -0
- package/dist/tools/prompts.js.map +1 -0
- package/dist/tools/protocol.d.ts +58 -0
- package/dist/tools/protocol.d.ts.map +1 -0
- package/dist/tools/protocol.js +287 -0
- package/dist/tools/protocol.js.map +1 -0
- package/dist/tools/repair.d.ts +83 -0
- package/dist/tools/repair.d.ts.map +1 -0
- package/dist/tools/repair.js +510 -0
- package/dist/tools/repair.js.map +1 -0
- package/dist/tools/workspace.d.ts +40 -0
- package/dist/tools/workspace.d.ts.map +1 -0
- package/dist/tools/workspace.js +224 -0
- package/dist/tools/workspace.js.map +1 -0
- package/dist/types/message.d.ts +87 -0
- package/dist/types/message.d.ts.map +1 -0
- package/dist/types/message.js +85 -0
- package/dist/types/message.js.map +1 -0
- package/dist/types/openai.d.ts +100 -0
- package/dist/types/openai.d.ts.map +1 -0
- package/dist/types/openai.js +66 -0
- package/dist/types/openai.js.map +1 -0
- package/dist/utils/errors.d.ts +82 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +115 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/mutex.d.ts +31 -0
- package/dist/utils/mutex.d.ts.map +1 -0
- package/dist/utils/mutex.js +61 -0
- package/dist/utils/mutex.js.map +1 -0
- package/dist/utils/prompt.d.ts +150 -0
- package/dist/utils/prompt.d.ts.map +1 -0
- package/dist/utils/prompt.js +514 -0
- package/dist/utils/prompt.js.map +1 -0
- package/dist/utils/text.d.ts +30 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +70 -0
- package/dist/utils/text.js.map +1 -0
- package/package.json +67 -4
- package/postinstall.mjs +34 -0
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 交互式登录 / 退出编排(`webapi login` / `webapi logout`)。
|
|
3
|
+
*
|
|
4
|
+
* ## 与 `auth-capture.ts` 的分工
|
|
5
|
+
* - `auth-capture.ts` —— **机制**:开浏览器、抓 cookie/bearer、原子落盘。它不知道
|
|
6
|
+
* 「用户是谁、想存成哪个账号」。
|
|
7
|
+
* - 本文件 —— **编排**:问用户选平台/账号、决定账号名、去重、汇报结果。
|
|
8
|
+
*
|
|
9
|
+
* ## 它解决的两个真问题
|
|
10
|
+
*
|
|
11
|
+
* ### 1. 多账号「怎么命名」
|
|
12
|
+
* 旧流程要求用户**自己**想账号名(`webapi login chatglm --account acc2`),
|
|
13
|
+
* 于是出现了大量 `acc2` / `test` / `a` 这种名字 —— 过两周没人记得谁是谁。
|
|
14
|
+
* 现在:捕获完直接**用平台返回的身份**(用户名)派生账号名,
|
|
15
|
+
* 用户只需在确有歧义时确认一下。
|
|
16
|
+
*
|
|
17
|
+
* ### 2. 「以为是两个账号,其实是同一个人」(最贵的坑)
|
|
18
|
+
* 系统 Firefox 常带着**上一个账号**的登录态,于是第二次登录抓到的还是同一个人。
|
|
19
|
+
* 旧流程只在文案里提醒「请先退出登录」,实际不校验 —— 而后果很实在:
|
|
20
|
+
* `ModelRouter` 会把它们当成两个账号启用「辅助通道并行」,
|
|
21
|
+
* 然后主对话和压缩请求打同一个账号,**立刻**收到
|
|
22
|
+
* 「请等待其他对话生成完毕」,整个请求作废。
|
|
23
|
+
*
|
|
24
|
+
* 现在:捕获后**硬校验** Cookie 指纹与身份,把结论摆给用户:
|
|
25
|
+
* - 指纹完全一致 → 「这和账号 X 是同一个登录态」(可选覆盖 X / 另存新账号)
|
|
26
|
+
* - 身份一致但指纹不同 → 「同一个人重新登录」(建议直接更新 X)
|
|
27
|
+
*/
|
|
28
|
+
import { existsSync, rmSync } from 'node:fs';
|
|
29
|
+
import { AuthCapture } from './auth-capture.js';
|
|
30
|
+
import { authFilePath, cookieFingerprint, listAccounts, loadAuth, } from './credentials.js';
|
|
31
|
+
import { extractAccountInfoSync, PLATFORMS, PLATFORM_LIST, platformDisplayName, } from './platforms.js';
|
|
32
|
+
import { logger } from '../log/logger.js';
|
|
33
|
+
import { bold, confirmYesNo, cyan, dim, isInteractive, selectOne, } from '../utils/prompt.js';
|
|
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 function detectDuplicate(captured, existing) {
|
|
51
|
+
if (captured.cookies > 0) {
|
|
52
|
+
const sameSession = existing.find((acc) => acc.cookies > 0 && acc.fingerprint === captured.fingerprint);
|
|
53
|
+
if (sameSession)
|
|
54
|
+
return { kind: 'same-session', accountId: sameSession.id };
|
|
55
|
+
}
|
|
56
|
+
const identity = captured.identity.trim();
|
|
57
|
+
if (identity && identity !== 'unknown') {
|
|
58
|
+
const samePerson = existing.find((acc) => acc.identity.trim() === identity);
|
|
59
|
+
if (samePerson)
|
|
60
|
+
return { kind: 'same-identity', accountId: samePerson.id };
|
|
61
|
+
}
|
|
62
|
+
return { kind: 'fresh' };
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 把任意字符串(用户名 / uid / 用户输入)洗成能当文件名的形式。
|
|
66
|
+
*
|
|
67
|
+
* 规则:非 `[A-Za-z0-9._-]` 的字符全部折成 `-`,合并连续分隔符、去掉首尾分隔符、
|
|
68
|
+
* 转小写、截断到 32 字符。
|
|
69
|
+
*
|
|
70
|
+
* ⚠️ 洗不出东西时返回**空串**(而不是兜底成某个词):中文用户名就属于这种,
|
|
71
|
+
* 调用方需要知道「这个候选废了」才能退到下一个候选(见 {@link deriveAccountId})。
|
|
72
|
+
*
|
|
73
|
+
* ⚠️ 返回值一定满足 `^[A-Za-z0-9._-]*$` 且不含 `/` —— 账号 ID 会被当作文件名
|
|
74
|
+
* 拼接,这是防路径穿越的第一道闸(`AuthCapture.saveAs` 还有第二道硬校验)。
|
|
75
|
+
*/
|
|
76
|
+
export function toSlug(raw) {
|
|
77
|
+
return (raw || '')
|
|
78
|
+
.normalize('NFKD')
|
|
79
|
+
.replace(/[^A-Za-z0-9._-]+/g, '-')
|
|
80
|
+
.replace(/-{2,}/g, '-')
|
|
81
|
+
.replace(/^[-._]+/, '')
|
|
82
|
+
.slice(0, 32)
|
|
83
|
+
.replace(/[-._]+$/, '')
|
|
84
|
+
.toLowerCase();
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* 洗成**唯一**的账号 ID,可直接当文件名。
|
|
88
|
+
*
|
|
89
|
+
* ⚠️ **必须去重**:`existing` 里已有的名字要避开(`alice` → `alice-2`)。
|
|
90
|
+
* 否则第二次登录同一个平台会把第一个账号的文件**原地覆盖**。
|
|
91
|
+
*/
|
|
92
|
+
export function slugAccountId(raw, existing = []) {
|
|
93
|
+
const cleaned = toSlug(raw);
|
|
94
|
+
const safe = cleaned === '' || cleaned === '.' || cleaned === '..' ? 'account' : cleaned;
|
|
95
|
+
const taken = new Set(existing);
|
|
96
|
+
if (!taken.has(safe))
|
|
97
|
+
return safe;
|
|
98
|
+
for (let n = 2; n < 1000; n += 1) {
|
|
99
|
+
const candidate = `${safe.slice(0, 28)}-${n}`;
|
|
100
|
+
if (!taken.has(candidate))
|
|
101
|
+
return candidate;
|
|
102
|
+
}
|
|
103
|
+
return `${safe.slice(0, 24)}-${Date.now()}`;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 按优先级给账号挑一个名字。
|
|
107
|
+
*
|
|
108
|
+
* 顺序:用户显式给的 → 身份标签(用户名)→ 身份标识(uid)→ `account`。
|
|
109
|
+
* 逐个尝试而不是只用第一个,是因为中文用户名洗完是空串,
|
|
110
|
+
* 那时应该退到 uid,而不是直接落到无意义的 `account`。
|
|
111
|
+
*/
|
|
112
|
+
export function deriveAccountId(candidates, existing = []) {
|
|
113
|
+
const picked = candidates.map((c) => toSlug(c ?? '')).find((slug) => slug !== '') ?? '';
|
|
114
|
+
return slugAccountId(picked, existing);
|
|
115
|
+
}
|
|
116
|
+
/* ==================================================================== */
|
|
117
|
+
/* 磁盘读取 */
|
|
118
|
+
/* ==================================================================== */
|
|
119
|
+
/**
|
|
120
|
+
* 读出某平台已有的全部账号(含身份与指纹)。
|
|
121
|
+
*
|
|
122
|
+
* ⚠️ **只返回「能用的」账号**:`loadAuth` 会挡掉没有 cookie 或 JSON 损坏的文件,
|
|
123
|
+
* 而那些文件不应该参与「这是不是同一个人」的判断(它们根本没会话可比)。
|
|
124
|
+
* 需要**列出全部文件**(用来删除)请用 `listAccounts`。
|
|
125
|
+
*
|
|
126
|
+
* @param authDir 凭证目录(默认 `settings.authDir`,测试时传临时目录)
|
|
127
|
+
*/
|
|
128
|
+
export function readExistingAccounts(platform, authDir) {
|
|
129
|
+
const out = [];
|
|
130
|
+
for (const id of listAccounts(platform, authDir)) {
|
|
131
|
+
const auth = loadAuth(platform, { accountId: id, authDir });
|
|
132
|
+
if (!auth)
|
|
133
|
+
continue;
|
|
134
|
+
const info = extractAccountInfoSync(platform, auth);
|
|
135
|
+
const cookies = auth.cookies ?? [];
|
|
136
|
+
out.push({
|
|
137
|
+
id,
|
|
138
|
+
identity: info['identifier'] ?? '',
|
|
139
|
+
label: info['label'] ?? '',
|
|
140
|
+
fingerprint: cookieFingerprint(cookies),
|
|
141
|
+
cookies: cookies.length,
|
|
142
|
+
capturedAt: auth.captured_at ?? 0,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
147
|
+
/** 已经存在的账号总数(含各平台,用于全局提示)。 */
|
|
148
|
+
function totalAccountCount() {
|
|
149
|
+
return PLATFORM_LIST.reduce((sum, spec) => sum + listAccounts(spec.id).length, 0);
|
|
150
|
+
}
|
|
151
|
+
/* ==================================================================== */
|
|
152
|
+
/* 菜单构造 */
|
|
153
|
+
/* ==================================================================== */
|
|
154
|
+
/** 平台选项:带账号数与「能否对话」的提示。 */
|
|
155
|
+
function platformChoices(options = {}) {
|
|
156
|
+
const choices = [];
|
|
157
|
+
for (const spec of PLATFORM_LIST) {
|
|
158
|
+
const count = listAccounts(spec.id).length;
|
|
159
|
+
if (options.onlyWithAccounts && count === 0)
|
|
160
|
+
continue;
|
|
161
|
+
const hints = [count > 0 ? `${count} 个账号` : '尚未登录'];
|
|
162
|
+
// 未实现 Provider 的平台**照样列出来**(这是「预留」对用户的可见形式),
|
|
163
|
+
// 但明确标注,避免用户以为登录完就能用。
|
|
164
|
+
if (!spec.providerImplemented)
|
|
165
|
+
hints.push('暂不能对话');
|
|
166
|
+
choices.push({ value: spec.id, label: spec.displayName, hint: hints.join(' · ') });
|
|
167
|
+
}
|
|
168
|
+
return choices;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* `login` 的动作菜单(纯函数,可单测)。
|
|
172
|
+
*
|
|
173
|
+
* ⚠️ 最后一项是**导航项**(`Symbol`),不是账号 ID —— 抽成纯函数就是为了让
|
|
174
|
+
* 「`canGoBack` 时给返回、否则给取消」这条规则能被测试钉住:它是唯一
|
|
175
|
+
* 决定「用户能不能退回去」的地方,改了没有任何别的东西会报错。
|
|
176
|
+
*
|
|
177
|
+
* @param canGoBack 平台是**从菜单选的**才为 true(命令行给的平台没有上一步)
|
|
178
|
+
*/
|
|
179
|
+
export function buildLoginActionChoices(existing, options) {
|
|
180
|
+
return [
|
|
181
|
+
{
|
|
182
|
+
value: '__new__',
|
|
183
|
+
label: '➕ 添加新账号',
|
|
184
|
+
hint: existing.length > 0 ? '登录另一个账号(完成后按身份自动命名)' : '(首次登录)',
|
|
185
|
+
},
|
|
186
|
+
...existing.map((acc) => ({
|
|
187
|
+
value: acc.id,
|
|
188
|
+
label: `♻️ 重新登录 ${acc.id}`,
|
|
189
|
+
hint: `${acc.label} · ${acc.cookies} 个 cookie(cookie 过期时用这个刷新)`,
|
|
190
|
+
})),
|
|
191
|
+
options.canGoBack
|
|
192
|
+
? { value: BACK, label: '← 返回上一步(重新选平台)' }
|
|
193
|
+
: { value: ABORT, label: '✗ 取消', hint: '等同按 Esc' },
|
|
194
|
+
];
|
|
195
|
+
}
|
|
196
|
+
/** 交互式确认;`yes` 直接通过,非交互且未给 `yes` 时返回 null(无法确认)。 */
|
|
197
|
+
async function confirmOrSkip(message, interactive, yes) {
|
|
198
|
+
if (yes)
|
|
199
|
+
return true;
|
|
200
|
+
if (!interactive)
|
|
201
|
+
return null;
|
|
202
|
+
return confirmYesNo({ message, defaultYes: true });
|
|
203
|
+
}
|
|
204
|
+
/** 用户主动取消(Esc / Ctrl+C / EOF)的退出码(shell 惯例 128+SIGINT)。 */
|
|
205
|
+
const EXIT_CANCELLED = 130;
|
|
206
|
+
/**
|
|
207
|
+
* 菜单里的「返回上一步」哨兵。
|
|
208
|
+
*
|
|
209
|
+
* ⚠️ 用 `Symbol` 而不是 `'__back__'` 这类字符串:菜单选项的值里混着
|
|
210
|
+
* **真实账号 ID**,总有一天会和某个账号名撞上 —— 而且不会报错,
|
|
211
|
+
* 只表现为「选那个账号时莫名回到了上一步」。
|
|
212
|
+
*/
|
|
213
|
+
const BACK = Symbol('back');
|
|
214
|
+
/** 菜单里的「退出 / 取消」哨兵(与 {@link BACK} 区分:一个是回上一步,一个是结束)。 */
|
|
215
|
+
const ABORT = Symbol('abort');
|
|
216
|
+
/**
|
|
217
|
+
* `webapi login` 的完整流程。
|
|
218
|
+
*
|
|
219
|
+
* ## 导航模型
|
|
220
|
+
* 交互式登录是**两级**的(选平台 → 选动作),所以用一个小循环 + 显式哨兵
|
|
221
|
+
* 而不是一串顺序执行的 `if`:
|
|
222
|
+
*
|
|
223
|
+
* ```
|
|
224
|
+
* 平台菜单 ──选平台──▶ 动作菜单 ──选动作──▶ 开始捕获
|
|
225
|
+
* ▲ │
|
|
226
|
+
* └──── 「← 返回上一步」─┘
|
|
227
|
+
* ```
|
|
228
|
+
*
|
|
229
|
+
* ⚠️ **只从平台菜单进来的才有「上一步」**:`webapi login chatglm` 是用户在命令行
|
|
230
|
+
* 明确指定的平台,没有可返回的地方,那里给的是「✗ 取消」。
|
|
231
|
+
*
|
|
232
|
+
* ⚠️ 动作菜单**即使 0 个账号也照样显示**(此时只有「添加新账号」+ 返回/取消)。
|
|
233
|
+
* 看起来多按一次回车,换来的是「开了浏览器才发现平台选错」时还能退出来
|
|
234
|
+
* —— 浏览器一旦启动就得等它登录完或 Ctrl+C。
|
|
235
|
+
*
|
|
236
|
+
* @returns 退出码:0 成功 / 1 失败 / 130 用户取消
|
|
237
|
+
*/
|
|
238
|
+
export async function runLogin(options = {}) {
|
|
239
|
+
const interactive = isInteractive() && !options.noInput;
|
|
240
|
+
/** 平台来自命令行 → 没有「上一步」可返回。 */
|
|
241
|
+
const platformFromCli = options.platform;
|
|
242
|
+
let platform = platformFromCli ?? '';
|
|
243
|
+
for (;;) {
|
|
244
|
+
/* ---------------- 1. 选定平台 ---------------- */
|
|
245
|
+
if (!platform) {
|
|
246
|
+
if (!interactive) {
|
|
247
|
+
console.error('非交互环境必须指定平台:webapi login <platform>\n' +
|
|
248
|
+
`可用平台: ${PLATFORM_LIST.map((s) => s.id).join(', ')}`);
|
|
249
|
+
return 1;
|
|
250
|
+
}
|
|
251
|
+
// 平台菜单里不会出现 BACK(没有上一步)→ 类型只放宽到 ABORT,
|
|
252
|
+
// 这样 `picked === ABORT` 之后 TS 就能收窄成 string
|
|
253
|
+
const picked = await selectOne({
|
|
254
|
+
message: '要登录哪个平台?',
|
|
255
|
+
choices: [...platformChoices(), { value: ABORT, label: '✗ 退出', hint: '等同按 Esc' }],
|
|
256
|
+
});
|
|
257
|
+
if (picked === null || picked === ABORT)
|
|
258
|
+
return EXIT_CANCELLED;
|
|
259
|
+
platform = picked;
|
|
260
|
+
}
|
|
261
|
+
const spec = PLATFORMS[platform];
|
|
262
|
+
if (!spec) {
|
|
263
|
+
console.error(`未知平台: ${platform}\n可用平台: ${PLATFORM_LIST.map((s) => s.id).join(', ')}`);
|
|
264
|
+
return 1;
|
|
265
|
+
}
|
|
266
|
+
/* ---------------- 2. 未实现对话的平台:先说清楚 ---------------- */
|
|
267
|
+
if (!spec.providerImplemented) {
|
|
268
|
+
console.log(`\n⚠️ ${platformDisplayName(platform)} 尚未实现对话能力:` +
|
|
269
|
+
'捕获到的凭证现在还用不上,\n' +
|
|
270
|
+
' 只是先存下来(将来 Provider 就绪后可直接复用,无需重新登录)。');
|
|
271
|
+
const proceed = await confirmOrSkip('仍然要捕获它的凭证吗?', interactive, options.yes ?? false);
|
|
272
|
+
if (proceed !== true) {
|
|
273
|
+
if (proceed === null) {
|
|
274
|
+
console.error('非交互环境下不继续(需要 --yes 才确认)。');
|
|
275
|
+
return 1;
|
|
276
|
+
}
|
|
277
|
+
// 用户不想捕获 → 回平台菜单(他大概是想换个平台),而不是直接退出
|
|
278
|
+
if (!platformFromCli) {
|
|
279
|
+
platform = '';
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
console.log('已取消。');
|
|
283
|
+
return EXIT_CANCELLED;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/* ---------------- 3. 决定这次写进哪个账号 ---------------- */
|
|
287
|
+
const existing = readExistingAccounts(platform);
|
|
288
|
+
let targetAccountId = options.account ?? null;
|
|
289
|
+
if (targetAccountId === null && interactive) {
|
|
290
|
+
const action = await selectOne({
|
|
291
|
+
message: existing.length > 0
|
|
292
|
+
? `${spec.displayName} 已登录 ${existing.length} 个账号,这次要做什么?`
|
|
293
|
+
: `${spec.displayName} 还没有账号,开始登录?`,
|
|
294
|
+
choices: buildLoginActionChoices(existing, { canGoBack: !platformFromCli }),
|
|
295
|
+
});
|
|
296
|
+
if (action === null || action === ABORT)
|
|
297
|
+
return EXIT_CANCELLED;
|
|
298
|
+
if (action === BACK) {
|
|
299
|
+
platform = '';
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
targetAccountId = action === '__new__' ? null : action;
|
|
303
|
+
}
|
|
304
|
+
return loginOnPlatform({ platform, spec, existing, targetAccountId, options, interactive });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* 在某个平台上真正走完一次登录:抓凭证 → 定账号名(含重复身份校验)→ 落盘 → 汇报。
|
|
309
|
+
*
|
|
310
|
+
* 从 {@link runLogin} 里拆出来,是因为「选平台/选动作」那部分变成了带导航的循环;
|
|
311
|
+
* 这里则是**一条直路**(中间不再回头),两者混在一个函数里会让循环体长得没法读。
|
|
312
|
+
*/
|
|
313
|
+
async function loginOnPlatform(ctx) {
|
|
314
|
+
const { platform, spec, existing, targetAccountId, options, interactive } = ctx;
|
|
315
|
+
const existingIds = existing.map((acc) => acc.id);
|
|
316
|
+
/* ---------------- 抓凭证 ---------------- */
|
|
317
|
+
if (existing.length > 0 && targetAccountId === null) {
|
|
318
|
+
console.log(`\n${bold('⚠️ 请先在打开的浏览器里退出当前账号,再登录目标账号。')}\n` +
|
|
319
|
+
' 否则抓到的还是上一个人 —— 抓完会打印身份给你核对。\n' +
|
|
320
|
+
` 已有: ${existing.map((acc) => `${acc.id}(${acc.label})`).join(', ')}`);
|
|
321
|
+
}
|
|
322
|
+
if (existing.length > 0) {
|
|
323
|
+
console.log(`\n(当前浏览器里可能是上面的登录态。清不掉时,可在浏览器里开一个隐私窗口登录。)`);
|
|
324
|
+
}
|
|
325
|
+
const capture = new AuthCapture(platform, {
|
|
326
|
+
accountId: targetAccountId ?? '__pending__',
|
|
327
|
+
headless: false,
|
|
328
|
+
// 先不落盘:等拿到身份、定好账号名再写(见 AuthCaptureOptions.saveOnCapture)
|
|
329
|
+
saveOnCapture: false,
|
|
330
|
+
});
|
|
331
|
+
let captured;
|
|
332
|
+
let bearer = '';
|
|
333
|
+
try {
|
|
334
|
+
const auth = await capture.capture();
|
|
335
|
+
const info = auth.account_info ?? extractAccountInfoSync(platform, auth);
|
|
336
|
+
const cookies = auth.cookies ?? [];
|
|
337
|
+
bearer = auth.bearer ?? '';
|
|
338
|
+
captured = {
|
|
339
|
+
identity: info['identifier'] ?? '',
|
|
340
|
+
label: info['label'] ?? '',
|
|
341
|
+
fingerprint: cookieFingerprint(cookies),
|
|
342
|
+
cookies: cookies.length,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
console.error(`捕获失败: ${String(error)}`);
|
|
347
|
+
return 1;
|
|
348
|
+
}
|
|
349
|
+
if (captured.cookies === 0) {
|
|
350
|
+
console.error('❌ 没有抓到任何 cookie —— 可能没登录成功。未写入任何文件。');
|
|
351
|
+
return 1;
|
|
352
|
+
}
|
|
353
|
+
/* ---------------- 4. 定账号名(含去重校验) ---------------- */
|
|
354
|
+
let finalId;
|
|
355
|
+
if (targetAccountId !== null) {
|
|
356
|
+
// 用户明确指定了目标账号:核对「登录的身份」和「要更新的人」是否一致
|
|
357
|
+
finalId = targetAccountId;
|
|
358
|
+
const others = existing.filter((acc) => acc.id !== targetAccountId);
|
|
359
|
+
const verdict = detectDuplicate(captured, others);
|
|
360
|
+
if (verdict.kind !== 'fresh') {
|
|
361
|
+
const same = verdict.kind === 'same-session'
|
|
362
|
+
? `与 ${verdict.accountId} 的 Cookie 完全一致(同一个登录态)`
|
|
363
|
+
: `就是 ${verdict.accountId} 这个人`;
|
|
364
|
+
console.log(`\n⚠️ 你登录的身份${same},但指定要写入 ${targetAccountId}。`);
|
|
365
|
+
const proceed = await confirmOrSkip(`确定要把 ${verdict.accountId} 的凭证写进 ${targetAccountId} 吗?`, interactive, options.yes ?? false);
|
|
366
|
+
if (proceed !== true) {
|
|
367
|
+
console.log('已取消,未写入任何文件。');
|
|
368
|
+
return proceed === null ? 1 : EXIT_CANCELLED;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
const verdict = detectDuplicate(captured, existing);
|
|
374
|
+
if (verdict.kind === 'fresh') {
|
|
375
|
+
// 关键体验:账号名**由身份派生**,用户不用自己想 name
|
|
376
|
+
finalId = deriveAccountId([captured.label, captured.identity], existingIds);
|
|
377
|
+
}
|
|
378
|
+
else if (!interactive) {
|
|
379
|
+
// 非交互:**更新原账号**而不是新建一个 —— 这是唯一无损的选择。
|
|
380
|
+
// (新建会留下两个「同一个人」的账号文件,正是辅助通道并行时
|
|
381
|
+
// 「请等待其他对话生成完毕」的成因。)
|
|
382
|
+
finalId = verdict.accountId;
|
|
383
|
+
const why = verdict.kind === 'same-session' ? 'Cookie 完全一致' : '身份一致';
|
|
384
|
+
console.log(`\n⚠️ 这份凭证与已有账号 ${finalId} ${why}(同一个人)→ 直接更新该账号。`);
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
const why = verdict.kind === 'same-session'
|
|
388
|
+
? `Cookie 与 ${verdict.accountId} 完全一致`
|
|
389
|
+
: `身份与 ${verdict.accountId} 一致(同一个人)`;
|
|
390
|
+
console.log(`\n⚠️ 这份凭证的${why}。`);
|
|
391
|
+
const action = await selectOne({
|
|
392
|
+
message: '很可能是同一个人的登录态,怎么处理?',
|
|
393
|
+
choices: [
|
|
394
|
+
{
|
|
395
|
+
value: 'update',
|
|
396
|
+
label: `♻️ 更新账号 ${verdict.accountId}`,
|
|
397
|
+
hint: '推荐:本来就是同一个人(如 cookie 过期后重新登录)',
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
value: 'new',
|
|
401
|
+
label: '➕ 另存为新账号',
|
|
402
|
+
hint: '只有你确定这是**另一个人**时才选(辅助通道需要真的不同账号)',
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
value: 'abort',
|
|
406
|
+
label: '✗ 取消',
|
|
407
|
+
hint: '我要登录的是另一个人 → 请先在浏览器里退出登录,再重跑本命令',
|
|
408
|
+
},
|
|
409
|
+
],
|
|
410
|
+
});
|
|
411
|
+
if (action === null)
|
|
412
|
+
return EXIT_CANCELLED;
|
|
413
|
+
if (action === 'abort') {
|
|
414
|
+
console.log('已取消,未写入任何文件。');
|
|
415
|
+
return 1;
|
|
416
|
+
}
|
|
417
|
+
finalId =
|
|
418
|
+
action === 'update'
|
|
419
|
+
? verdict.accountId
|
|
420
|
+
: deriveAccountId([captured.label, captured.identity], existingIds);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
/* ---------------- 5. 落盘 ---------------- */
|
|
424
|
+
let file;
|
|
425
|
+
try {
|
|
426
|
+
file = capture.saveAs(finalId);
|
|
427
|
+
}
|
|
428
|
+
catch (error) {
|
|
429
|
+
console.error(`保存凭证失败: ${String(error)}`);
|
|
430
|
+
return 1;
|
|
431
|
+
}
|
|
432
|
+
/* ---------------- 6. 汇报 ---------------- */
|
|
433
|
+
const after = readExistingAccounts(platform);
|
|
434
|
+
// 记一条调试日志:支持时最常见的问题是「账号名怎么来的 / 为什么覆盖了别人」,
|
|
435
|
+
// 控制台只有结论,日志里留一份「输入 → 判定 → 最终 id」的链条。
|
|
436
|
+
logger.info(`[login] ${platform}/${finalId} 凭证已保存` +
|
|
437
|
+
`(身份=${captured.label}/${captured.identity}, cookie=${captured.cookies}, ` +
|
|
438
|
+
`本次指定账号=${targetAccountId ?? '自动派生'}, 保存后账号数=${after.length})`);
|
|
439
|
+
console.log('');
|
|
440
|
+
console.log(`${cyan('✔')} 凭证已保存`);
|
|
441
|
+
console.log(` 平台: ${spec.displayName} (${platform})`);
|
|
442
|
+
console.log(` 账号: ${bold(finalId)}`);
|
|
443
|
+
console.log(` 身份: ${bold(captured.label)} ← 请核对是不是你想登录的那个人`);
|
|
444
|
+
console.log(` Cookie: ${captured.cookies} 个${bearer ? ' · bearer: 有' : ''}`);
|
|
445
|
+
console.log(` 文件: ${file}`);
|
|
446
|
+
if (after.length >= 2) {
|
|
447
|
+
console.log('');
|
|
448
|
+
console.log(` ${cyan('✓')} ${spec.displayName} 现有 ${after.length} 个账号:`);
|
|
449
|
+
for (const acc of after) {
|
|
450
|
+
console.log(` ${acc.id.padEnd(16)} ${acc.label}`);
|
|
451
|
+
}
|
|
452
|
+
console.log(' → 辅助通道(压缩/转换与主对话并行)可以启用了。');
|
|
453
|
+
}
|
|
454
|
+
else if (totalAccountCount() === after.length) {
|
|
455
|
+
console.log('');
|
|
456
|
+
console.log(` 提示: 只有 1 个账号时,压缩/转换会与主对话**串行**(功能正常,只是慢)。\n` +
|
|
457
|
+
` 想并行再加一个账号: webapi login ${platform} --account acc2`);
|
|
458
|
+
}
|
|
459
|
+
console.log('');
|
|
460
|
+
console.log('下一步:');
|
|
461
|
+
console.log(` ${dim('webapi accounts 查看账号与角色分配')}`);
|
|
462
|
+
console.log(` ${dim('webapi start 启动服务')}`);
|
|
463
|
+
console.log(` ${dim('(服务正在运行的话,重启它或等 30s 让辅助通道重扫)')}`);
|
|
464
|
+
return 0;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* `webapi logout` 的完整流程。
|
|
468
|
+
*
|
|
469
|
+
* ## ⚠️ 这里修掉了一个**会静默删错文件**的老问题
|
|
470
|
+
* 旧实现是 `webapi logout <platform> [--account x]`,`account` 缺省值写死为
|
|
471
|
+
* `'default'`。于是 `webapi logout chatglm`(本意可能只是「看看怎么用」)
|
|
472
|
+
* **直接把 default 账号的凭证删掉了**,而且只在 stdout 说一句「已删除」。
|
|
473
|
+
*
|
|
474
|
+
* 现在:账号必须**显式给出**(`--account`)或**从菜单里选**;
|
|
475
|
+
* 非交互且没给 `--account` 时**直接报错退出**,绝不替用户猜。
|
|
476
|
+
*
|
|
477
|
+
* @returns 退出码:0 成功 / 1 失败或未确认 / 130 用户取消
|
|
478
|
+
*/
|
|
479
|
+
export async function runLogout(options = {}) {
|
|
480
|
+
const interactive = isInteractive() && !options.noInput;
|
|
481
|
+
/** 平台来自命令行 → 没有「上一步」可返回。 */
|
|
482
|
+
const platformFromCli = options.platform;
|
|
483
|
+
let platform = platformFromCli ?? '';
|
|
484
|
+
for (;;) {
|
|
485
|
+
/* ---------------- 1. 选定平台 ---------------- */
|
|
486
|
+
if (!platform) {
|
|
487
|
+
if (!interactive) {
|
|
488
|
+
console.error('非交互环境必须指定平台:webapi logout <platform> --account <id> --yes');
|
|
489
|
+
return 1;
|
|
490
|
+
}
|
|
491
|
+
const platformOptions = platformChoices({ onlyWithAccounts: true });
|
|
492
|
+
if (platformOptions.length === 0) {
|
|
493
|
+
console.log('没有任何已捕获的凭证,无需退出登录。');
|
|
494
|
+
return 0;
|
|
495
|
+
}
|
|
496
|
+
// 平台菜单没有上一步 → 类型只放宽到 ABORT(见 runLogin 里的同款说明)
|
|
497
|
+
const picked = await selectOne({
|
|
498
|
+
message: '要退出哪个平台的登录?',
|
|
499
|
+
choices: [
|
|
500
|
+
...platformOptions,
|
|
501
|
+
{ value: ABORT, label: '✗ 退出', hint: '等同按 Esc' },
|
|
502
|
+
],
|
|
503
|
+
});
|
|
504
|
+
if (picked === null || picked === ABORT)
|
|
505
|
+
return EXIT_CANCELLED;
|
|
506
|
+
platform = picked;
|
|
507
|
+
}
|
|
508
|
+
if (!PLATFORMS[platform]) {
|
|
509
|
+
console.error(`未知平台: ${platform}`);
|
|
510
|
+
return 1;
|
|
511
|
+
}
|
|
512
|
+
/* ---------------- 2. 选定账号 ---------------- */
|
|
513
|
+
// ⚠️ 用 `listAccounts`(**按文件列**)而不是 `readExistingAccounts`
|
|
514
|
+
// (会被 `loadAuth` 过滤掉无 cookie / JSON 损坏的文件):
|
|
515
|
+
// 退出登录的职责是「把文件删掉」,那些坏文件**恰恰最需要能删**,
|
|
516
|
+
// 否则用户会卡在「明明有个账号文件,但删不掉、也用不了」。
|
|
517
|
+
const ids = listAccounts(platform);
|
|
518
|
+
if (ids.length === 0) {
|
|
519
|
+
// 只可能是命令行显式指定的平台(菜单里的平台都有账号)
|
|
520
|
+
console.log(`${platformDisplayName(platform)} 没有任何凭证文件。`);
|
|
521
|
+
return 0;
|
|
522
|
+
}
|
|
523
|
+
let account = options.account;
|
|
524
|
+
if (!account) {
|
|
525
|
+
if (!interactive) {
|
|
526
|
+
console.error(`非交互环境必须明确指定账号:webapi logout ${platform} --account <id> --yes\n` +
|
|
527
|
+
`现有账号: ${ids.join(', ')}`);
|
|
528
|
+
return 1;
|
|
529
|
+
}
|
|
530
|
+
const choices = ids.map((id) => {
|
|
531
|
+
const auth = loadAuth(platform, { accountId: id });
|
|
532
|
+
const label = auth?.account_info?.label ?? auth?.account_info?.identifier ?? '未知身份';
|
|
533
|
+
const cookies = auth?.cookies?.length ?? 0;
|
|
534
|
+
return {
|
|
535
|
+
value: id,
|
|
536
|
+
label: id,
|
|
537
|
+
hint: cookies > 0 ? `${label} · ${cookies} 个 cookie` : '⚠️ 无可用 cookie(损坏或未抓全)',
|
|
538
|
+
};
|
|
539
|
+
});
|
|
540
|
+
choices.push(
|
|
541
|
+
// 有上一步就给「返回」,没有就给「取消」(语义不同,不能混用同一个哨兵)
|
|
542
|
+
platformFromCli
|
|
543
|
+
? { value: ABORT, label: '✗ 取消', hint: '等同按 Esc' }
|
|
544
|
+
: { value: BACK, label: '← 返回上一步(重新选平台)' });
|
|
545
|
+
const picked = await selectOne({
|
|
546
|
+
message: `要删除 ${platformDisplayName(platform)} 的哪个账号?`,
|
|
547
|
+
choices,
|
|
548
|
+
});
|
|
549
|
+
if (picked === null || picked === ABORT)
|
|
550
|
+
return EXIT_CANCELLED;
|
|
551
|
+
if (picked === BACK) {
|
|
552
|
+
platform = '';
|
|
553
|
+
continue;
|
|
554
|
+
}
|
|
555
|
+
account = picked;
|
|
556
|
+
}
|
|
557
|
+
if (!ids.includes(account)) {
|
|
558
|
+
console.error(`账号 ${account} 不存在。现有账号: ${ids.join(', ')}`);
|
|
559
|
+
return 1;
|
|
560
|
+
}
|
|
561
|
+
return deleteAccount({ platform, account, interactive, yes: options.yes ?? false });
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* 确认并删除一个账号的凭证。
|
|
566
|
+
*
|
|
567
|
+
* 从 {@link runLogout} 拆出来:那边变成了带导航的循环,这里是一条直路
|
|
568
|
+
* (只有「确认 → 检查 → 删除」三步)。
|
|
569
|
+
*/
|
|
570
|
+
async function deleteAccount(ctx) {
|
|
571
|
+
const { platform, account, interactive, yes } = ctx;
|
|
572
|
+
const path = authFilePath(platform, account);
|
|
573
|
+
const auth = loadAuth(platform, { accountId: account });
|
|
574
|
+
const label = auth?.account_info?.label ?? auth?.account_info?.identifier ?? '未知身份';
|
|
575
|
+
const confirmed = await confirmOrSkip(`确认删除 ${platform}/${account}(${label})的凭证?`, interactive, yes);
|
|
576
|
+
if (confirmed !== true) {
|
|
577
|
+
if (confirmed === null) {
|
|
578
|
+
console.error('非交互环境不删除任何东西:请加 --yes 确认。');
|
|
579
|
+
return 1;
|
|
580
|
+
}
|
|
581
|
+
console.log('已取消,未删除任何文件。');
|
|
582
|
+
return 1;
|
|
583
|
+
}
|
|
584
|
+
if (!existsSync(path)) {
|
|
585
|
+
// 走到这里只可能是「文件在 listAccounts 之后、删除之前被删了」,属于并发操作
|
|
586
|
+
console.error(`凭证文件不存在(可能已被删除): ${path}`);
|
|
587
|
+
return 1;
|
|
588
|
+
}
|
|
589
|
+
try {
|
|
590
|
+
rmSync(path, { force: true });
|
|
591
|
+
}
|
|
592
|
+
catch (error) {
|
|
593
|
+
console.error(`删除失败: ${String(error)}`);
|
|
594
|
+
return 1;
|
|
595
|
+
}
|
|
596
|
+
const remaining = listAccounts(platform);
|
|
597
|
+
console.log(`${cyan('✔')} 已删除 ${platform}/${account}(${label})`);
|
|
598
|
+
console.log(` 文件: ${path}`);
|
|
599
|
+
console.log(remaining.length > 0
|
|
600
|
+
? ` 剩余账号: ${remaining.join(', ')}`
|
|
601
|
+
: ` 该平台已无账号。再登录: webapi login ${platform}`);
|
|
602
|
+
console.log('');
|
|
603
|
+
console.log('(服务正在运行的话,重启它或等 30s 让辅助通道重扫才会生效)');
|
|
604
|
+
return 0;
|
|
605
|
+
}
|
|
606
|
+
//# sourceMappingURL=login-flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-flow.js","sourceRoot":"","sources":["../../src/browser/login-flow.ts"],"names":[],"mappings":"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"}
|