magpie-gemini-web 0.5.0 → 0.5.1
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/README.en.md +9 -8
- package/README.md +9 -8
- package/lib/studio-native.mjs +1 -1
- package/lib/studio.mjs +130 -91
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -87,18 +87,19 @@ Uses Google AI Studio through [AIStudio2API](https://github.com/Mag1cFall/AIStud
|
|
|
87
87
|
|
|
88
88
|
### Getting started
|
|
89
89
|
|
|
90
|
-
1. Sign in to Google AI Studio and choose
|
|
91
|
-
2. Sign in to your Google account in the separate login window that opens (your usual browser is not affected), then close it. The first time, the login browser Camoufox is downloaded first, so the window can take a few minutes to appear; the login must finish within 15 minutes.
|
|
90
|
+
1. Sign in to Google AI Studio and choose **用 Google 账号登录(推荐)** (sign in with a Google account). The first time, the plugin downloads AIStudio2API, verifies its SHA-256 and starts it in the background.
|
|
91
|
+
2. Sign in to your Google account in the separate login window that opens (your usual browser is not affected), then close it. The first time, the login browser Camoufox (about 300 MB) is downloaded first, so the window can take a few minutes to appear while Magpie shows no change; the login must finish within 15 minutes.
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
Choosing it again later lists:
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
- **添加新的 Google 账号** (add a new Google account): opens the login window for another account;
|
|
96
|
+
- **the accounts already on this machine**: makes a card for one at once; one marked as needing to sign in again opens the login window to do so.
|
|
96
97
|
|
|
97
|
-
|
|
98
|
-
- **重新登录失效的 AI Studio 账号** (sign an expired account in again): when an account's Google login expires, choose it here to sign in again.
|
|
99
|
-
- **连接已有 AIStudio2API** (connect an existing AIStudio2API): if you run AIStudio2API yourself, enter its address (default `http://127.0.0.1:2048/v1`) and `PROXY_API_KEY`.
|
|
98
|
+
Each Google account gets a card of its own. As with Gemini Web, the local service picks the account for each request (one until it cools down, then the next), whichever card Magpie uses.
|
|
100
99
|
|
|
101
|
-
|
|
100
|
+
If you run AIStudio2API yourself, choose **连接已有 AIStudio2API** (connect an existing AIStudio2API) and enter its address (default `http://127.0.0.1:2048/v1`) and `PROXY_API_KEY`.
|
|
101
|
+
|
|
102
|
+
Usage card: AI Studio reports no remaining quota. The card shows the models the account is cooling down on and when each comes back, or that the account needs to sign in again.
|
|
102
103
|
|
|
103
104
|
### Plugin options
|
|
104
105
|
|
package/README.md
CHANGED
|
@@ -87,18 +87,19 @@ Magpie 的额度卡片会显示 Google 账号的 **5 小时** 和 **每周** 用
|
|
|
87
87
|
|
|
88
88
|
### 开始使用
|
|
89
89
|
|
|
90
|
-
1. 登录 Google AI Studio,选
|
|
91
|
-
2. 在弹出的独立登录窗口里登录 Google 账号(不影响你平时用的浏览器),完成后关掉窗口即可。第一次要先下载登录用的浏览器 Camoufox
|
|
90
|
+
1. 登录 Google AI Studio,选 **「用 Google 账号登录(推荐)」**。第一次用时,插件会自动下载 AIStudio2API、校验 SHA-256 并在后台启动。
|
|
91
|
+
2. 在弹出的独立登录窗口里登录 Google 账号(不影响你平时用的浏览器),完成后关掉窗口即可。第一次要先下载登录用的浏览器 Camoufox(约 300 MB),窗口可能要等几分钟才出现,期间 Magpie 里没有变化;需要在 15 分钟内完成登录。
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
之后再选「用 Google 账号登录」,会列出:
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
- **添加新的 Google 账号**:打开登录窗口,再加一个账号;
|
|
96
|
+
- **本机已有的账号**:直接给它建卡片;标着「需要重新登录」的账号会打开登录窗口重新登录。
|
|
96
97
|
|
|
97
|
-
|
|
98
|
-
- **重新登录失效的 AI Studio 账号**:账号的 Google 登录过期后,在这里选中它重新登录。
|
|
99
|
-
- **连接已有 AIStudio2API**:你自己运行了 AIStudio2API 时,填它的地址(默认 `http://127.0.0.1:2048/v1`)和 `PROXY_API_KEY`。
|
|
98
|
+
每个 Google 账号一张卡片。和 Gemini Web 一样,每个请求实际用哪个账号由本地服务决定(先用一个,冷却了再换下一个),Magpie 在卡片之间怎么切换不影响这一点。
|
|
100
99
|
|
|
101
|
-
|
|
100
|
+
如果你自己运行了 AIStudio2API,选 **「连接已有 AIStudio2API」**,填它的地址(默认 `http://127.0.0.1:2048/v1`)和 `PROXY_API_KEY`。
|
|
101
|
+
|
|
102
|
+
额度卡片:AI Studio 不提供剩余额度。卡片显示这个账号正在冷却的模型和恢复时间;账号需要重新登录时会提示。
|
|
102
103
|
|
|
103
104
|
### 插件选项
|
|
104
105
|
|
package/lib/studio-native.mjs
CHANGED
|
@@ -860,7 +860,7 @@ async function readyStudio(local, initial, options = {}) {
|
|
|
860
860
|
for (;;) {
|
|
861
861
|
if (status.running) return local;
|
|
862
862
|
if (needsSignIn(status.accounts)) {
|
|
863
|
-
throw new Error(`AI Studio cannot start: its Google accounts need to sign in again (${status.accounts.auth_required} of ${status.accounts.total}). In Magpie, sign in to AI Studio with "
|
|
863
|
+
throw new Error(`AI Studio cannot start: its Google accounts need to sign in again (${status.accounts.auth_required} of ${status.accounts.total}). In Magpie, sign in to Google AI Studio with "用 Google 账号登录(推荐)" and choose the account, or run: ${studioCommand('relogin')}`);
|
|
864
864
|
}
|
|
865
865
|
if (Date.now() >= deadline) {
|
|
866
866
|
throw new Error(`AI Studio generation did not become ready (state ${status.state}, ${status.accounts.ready ?? 0}/${status.accounts.total} accounts ready); see ${path.join(local.dataDir, 'backend.log')}`);
|
package/lib/studio.mjs
CHANGED
|
@@ -15,18 +15,28 @@ const LOGIN_TIMEOUT_MS = 15 * 60 * 1000;
|
|
|
15
15
|
// Upstream logs in with Camoufox even when generation runs in Go, and downloads it on the first
|
|
16
16
|
// login, so that one can take minutes before a window shows.
|
|
17
17
|
const LOGIN_WINDOW = [
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'请在 15 分钟内完成登录;登录完成后可以关掉窗口,日常生成不需要浏览器。'
|
|
18
|
+
'第一次登录要先下载登录用的浏览器 Camoufox(约 300 MB),可能要等几分钟窗口才出现,期间这里没有变化,请耐心等待。',
|
|
19
|
+
'登录窗口是独立的,不影响你平时用的浏览器;请在 15 分钟内完成登录,完成后可以关掉窗口,日常生成不需要浏览器。'
|
|
21
20
|
];
|
|
22
21
|
const LOGIN_STEPS = [
|
|
23
22
|
...LOGIN_WINDOW,
|
|
24
|
-
'
|
|
23
|
+
'想加更多 Google 账号,再来一次即可,每个账号一张卡片。'
|
|
25
24
|
].join('\n');
|
|
26
25
|
const RELOGIN_STEPS = LOGIN_WINDOW.join('\n');
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
26
|
+
// AdminAccount.state as the account list shows it
|
|
27
|
+
const ACCOUNT_STATES = {
|
|
28
|
+
ready: '可用',
|
|
29
|
+
busy: '使用中',
|
|
30
|
+
cooldown: '冷却中',
|
|
31
|
+
auth_required: '需要重新登录',
|
|
32
|
+
unavailable: '暂时不可用',
|
|
33
|
+
disabled: '已停用'
|
|
34
|
+
};
|
|
35
|
+
const SIGN_IN_METHOD = '用 Google 账号登录(推荐)';
|
|
36
|
+
// How to sign an account in again, or add one, as messages say it
|
|
37
|
+
const SIGN_IN_HOW = `在 Magpie 里登录 Google AI Studio,选「${SIGN_IN_METHOD}」`;
|
|
38
|
+
// The choice of a new account among the local service's (whose ids are emails, so none is this)
|
|
39
|
+
const NEW_ACCOUNT = '+new';
|
|
30
40
|
|
|
31
41
|
const KNOWN_STUDIO_NESTED = new Set([
|
|
32
42
|
'baseURL',
|
|
@@ -342,15 +352,16 @@ async function forwardManagedStudio(input, init, getAuth, opts) {
|
|
|
342
352
|
return forward(retryInput, init, getAuth, { ...opts, nativeThinking: true, stripCitations: false });
|
|
343
353
|
}
|
|
344
354
|
|
|
345
|
-
//
|
|
346
|
-
//
|
|
347
|
-
//
|
|
348
|
-
//
|
|
349
|
-
|
|
355
|
+
// accountSignIn is the Magpie sign-in for one Google account of the local service: the service's
|
|
356
|
+
// key, with the account's id for its usage card and its email (the account's label, or its id,
|
|
357
|
+
// which upstream makes the lowercased email), which names the card and keeps each account a
|
|
358
|
+
// sign-in of its own, as Gemini Web's are. The service still picks the account for each request
|
|
359
|
+
// itself (fill-first): a sign-in can't pin one.
|
|
360
|
+
function accountSignIn(local, account) {
|
|
350
361
|
return {
|
|
351
362
|
type: 'success',
|
|
352
363
|
key: local.apiKey,
|
|
353
|
-
metadata: { mode: 'studio', managed: true, baseURL: local.baseURL }
|
|
364
|
+
metadata: { mode: 'studio', managed: true, baseURL: local.baseURL, account: account.id, email: labelOf(account) }
|
|
354
365
|
};
|
|
355
366
|
}
|
|
356
367
|
|
|
@@ -390,13 +401,40 @@ export function cooldownWindows(cooldowns, accounts, now = Date.now()) {
|
|
|
390
401
|
return out.sort((a, b) => b.used - a.used || Date.parse(a.resetsAt) - Date.parse(b.resetsAt));
|
|
391
402
|
}
|
|
392
403
|
|
|
404
|
+
// accountUsage is the usage card of one account of the local service: its own cooldowns, one
|
|
405
|
+
// window a model (or one for all its models), full until the cooldown ends; an account that can't
|
|
406
|
+
// serve says why instead.
|
|
407
|
+
export function accountUsage(account, cooldowns, now = Date.now()) {
|
|
408
|
+
const user = labelOf(account);
|
|
409
|
+
if (account.state === 'auth_required') {
|
|
410
|
+
return { user, error: `这个 Google 账号需要重新登录:${SIGN_IN_HOW},再选这个账号`, windows: [] };
|
|
411
|
+
}
|
|
412
|
+
if (!SERVING_STATES.has(account.state)) {
|
|
413
|
+
const why = ACCOUNT_STATES[account.state] || account.state || '暂时不可用';
|
|
414
|
+
return { user, error: `这个 Google 账号${why}${account.message ? `:${account.message}` : ''}`, windows: [] };
|
|
415
|
+
}
|
|
416
|
+
const windows = [];
|
|
417
|
+
for (const c of cooldowns) {
|
|
418
|
+
const until = Date.parse(c?.until ?? '');
|
|
419
|
+
if (c?.account_id !== account.id || !Number.isFinite(until) || until <= now) continue;
|
|
420
|
+
const reason = typeof c.reason === 'string' ? c.reason.trim() : '';
|
|
421
|
+
windows.push({
|
|
422
|
+
name: typeof c.model_id === 'string' && c.model_id ? c.model_id : '所有模型',
|
|
423
|
+
used: 100,
|
|
424
|
+
resetsAt: new Date(until).toISOString(),
|
|
425
|
+
display: reason && reason.length <= 40 ? `冷却中:${reason}` : '冷却中'
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
return { user, windows: windows.sort((a, b) => Date.parse(a.resetsAt) - Date.parse(b.resetsAt)) };
|
|
429
|
+
}
|
|
430
|
+
|
|
393
431
|
// poolUsage is the usage card of the local service's accounts: they go by their labels (Google
|
|
394
432
|
// emails), with the ones that can't serve counted beside them. The service gives no allowance to
|
|
395
433
|
// show, only the models its accounts cool down on (see cooldownWindows); a pool none of whose
|
|
396
434
|
// accounts can serve until one signs in again is an error, since every request fails.
|
|
397
435
|
export function poolUsage(accounts, cooldowns, now = Date.now()) {
|
|
398
436
|
if (!accounts.length) {
|
|
399
|
-
return { error: `本地 AI Studio 里还没有 Google
|
|
437
|
+
return { error: `本地 AI Studio 里还没有 Google 账号:${SIGN_IN_HOW}`, windows: [] };
|
|
400
438
|
}
|
|
401
439
|
const expired = accounts.filter(a => a.state === 'auth_required').length;
|
|
402
440
|
const unavailable = accounts.filter(a => a.state === 'unavailable').length;
|
|
@@ -407,7 +445,7 @@ export function poolUsage(accounts, cooldowns, now = Date.now()) {
|
|
|
407
445
|
const user = notes.length ? `${named}(${notes.join(',')})` : named;
|
|
408
446
|
if (!accounts.some(a => SERVING_STATES.has(a.state))) {
|
|
409
447
|
const error = expired
|
|
410
|
-
? `${expired} 个 Google
|
|
448
|
+
? `${expired} 个 Google 账号都需要重新登录:${SIGN_IN_HOW},再选要重新登录的账号`
|
|
411
449
|
: '本地 AI Studio 的 Google 账号暂时都不可用';
|
|
412
450
|
return { user, error, windows: [] };
|
|
413
451
|
}
|
|
@@ -426,20 +464,56 @@ export const AIStudioPlugin = async (_input, options = {}) => {
|
|
|
426
464
|
// afterLogin is the sign-in once an account is signed in. Generation may still be starting;
|
|
427
465
|
// the first request waits for it, so a slow start doesn't fail a sign-in that worked (and a
|
|
428
466
|
// retry doesn't open another login window for the same account).
|
|
429
|
-
function afterLogin(local) {
|
|
467
|
+
function afterLogin(local, account) {
|
|
430
468
|
ensureStudio({ proxy: opts.proxy }).catch(err => {
|
|
431
469
|
console.error(`[ai-studio] generation did not start after sign-in: ${err.message}`);
|
|
432
470
|
});
|
|
433
|
-
return
|
|
471
|
+
return accountSignIn(local, account);
|
|
434
472
|
}
|
|
435
473
|
|
|
436
|
-
//
|
|
437
|
-
|
|
438
|
-
|
|
474
|
+
// addAccount signs a new Google account in through the service's own login window, setting the
|
|
475
|
+
// service up first if this is the first.
|
|
476
|
+
async function addAccount() {
|
|
439
477
|
await ensureStudio({ proxy: opts.proxy, managementOnly: true });
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
478
|
+
return {
|
|
479
|
+
url: '',
|
|
480
|
+
method: 'auto',
|
|
481
|
+
instructions: LOGIN_STEPS,
|
|
482
|
+
async callback() {
|
|
483
|
+
let local, account;
|
|
484
|
+
try {
|
|
485
|
+
local = await ensureStudio({ proxy: opts.proxy, managementOnly: true });
|
|
486
|
+
const res = await studioAdmin(local, 'POST', '/api/accounts', {}, { timeoutMs: LOGIN_TIMEOUT_MS });
|
|
487
|
+
account = res?.account;
|
|
488
|
+
if (!account || typeof account.id !== 'string' || !account.id || account.enabled === false) {
|
|
489
|
+
throw new Error('AIStudio2API did not return an enabled account');
|
|
490
|
+
}
|
|
491
|
+
} catch (err) {
|
|
492
|
+
return { type: 'failed', error: `Google 登录没有完成:${err.message}` };
|
|
493
|
+
}
|
|
494
|
+
return afterLogin(local, account);
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// signInAgain signs an account whose Google sign-in expired in again, in a login window.
|
|
500
|
+
function signInAgain(chosen) {
|
|
501
|
+
return {
|
|
502
|
+
url: '',
|
|
503
|
+
method: 'auto',
|
|
504
|
+
instructions: RELOGIN_STEPS,
|
|
505
|
+
async callback() {
|
|
506
|
+
let local;
|
|
507
|
+
try {
|
|
508
|
+
local = await ensureStudio({ proxy: opts.proxy, managementOnly: true });
|
|
509
|
+
const res = await studioAdmin(local, 'POST', `/api/accounts/${encodeURIComponent(chosen.id)}/login`, {}, { timeoutMs: LOGIN_TIMEOUT_MS });
|
|
510
|
+
if (res?.account?.state === 'auth_required') throw new Error(res.account.message || '账号仍然需要重新登录');
|
|
511
|
+
} catch (err) {
|
|
512
|
+
return { type: 'failed', error: `${labelOf(chosen)} 没有重新登录:${err.message}` };
|
|
513
|
+
}
|
|
514
|
+
return afterLogin(local, chosen);
|
|
515
|
+
}
|
|
516
|
+
};
|
|
443
517
|
}
|
|
444
518
|
|
|
445
519
|
return {
|
|
@@ -457,83 +531,39 @@ export const AIStudioPlugin = async (_input, options = {}) => {
|
|
|
457
531
|
maxConcurrency: 1,
|
|
458
532
|
methods: [
|
|
459
533
|
{
|
|
534
|
+
// One way in for a Google account: a new one, one the local service already has, or one
|
|
535
|
+
// of those to sign in again. The first time there is no service yet, and nothing to ask.
|
|
460
536
|
type: 'oauth',
|
|
461
|
-
label:
|
|
462
|
-
|
|
537
|
+
label: SIGN_IN_METHOD,
|
|
538
|
+
prompts: [{ type: 'select', key: 'account', message: '选择 Google 账号', options: [] }],
|
|
539
|
+
async ask(inputs) {
|
|
540
|
+
if (inputs?.account || !localStudio(opts)) return null;
|
|
463
541
|
await ensureStudio({ proxy: opts.proxy, managementOnly: true });
|
|
464
|
-
return {
|
|
465
|
-
url: '',
|
|
466
|
-
method: 'auto',
|
|
467
|
-
instructions: LOGIN_STEPS,
|
|
468
|
-
async callback() {
|
|
469
|
-
let local;
|
|
470
|
-
try {
|
|
471
|
-
local = await ensureStudio({ proxy: opts.proxy, managementOnly: true });
|
|
472
|
-
const res = await studioAdmin(local, 'POST', '/api/accounts', {}, { timeoutMs: LOGIN_TIMEOUT_MS });
|
|
473
|
-
const account = res?.account;
|
|
474
|
-
if (!account || typeof account.id !== 'string' || !account.id || account.enabled === false) {
|
|
475
|
-
throw new Error('AIStudio2API did not return an enabled account');
|
|
476
|
-
}
|
|
477
|
-
} catch (err) {
|
|
478
|
-
return { type: 'failed', error: `Google 登录没有完成:${err.message}` };
|
|
479
|
-
}
|
|
480
|
-
return afterLogin(local);
|
|
481
|
-
}
|
|
482
|
-
};
|
|
483
|
-
}
|
|
484
|
-
},
|
|
485
|
-
{
|
|
486
|
-
type: 'oauth',
|
|
487
|
-
label: '使用本机已有的 AI Studio 服务',
|
|
488
|
-
async authorize() {
|
|
489
|
-
// Only a setup that is already here has accounts to use: don't install one.
|
|
490
|
-
if (!localStudio(opts)) throw new Error(NO_LOCAL_STUDIO);
|
|
491
|
-
const local = await ensureStudio({ proxy: opts.proxy, managementOnly: true });
|
|
492
542
|
const accounts = await studioAccounts(opts);
|
|
493
|
-
if (!accounts.length)
|
|
494
|
-
return {
|
|
495
|
-
url: '',
|
|
496
|
-
method: 'auto',
|
|
497
|
-
instructions: '',
|
|
498
|
-
callback: async () => poolSignIn(local)
|
|
499
|
-
};
|
|
500
|
-
}
|
|
501
|
-
},
|
|
502
|
-
{
|
|
503
|
-
type: 'oauth',
|
|
504
|
-
label: RELOGIN_METHOD,
|
|
505
|
-
prompts: [{ type: 'select', key: 'account', message: '选择要重新登录的 Google 账号', options: [] }],
|
|
506
|
-
async ask(inputs) {
|
|
507
|
-
if (inputs?.account) return null;
|
|
508
|
-
const accounts = await expiredAccounts();
|
|
543
|
+
if (!accounts.length) return null;
|
|
509
544
|
return {
|
|
510
545
|
type: 'select',
|
|
511
546
|
key: 'account',
|
|
512
|
-
message: '
|
|
547
|
+
message: '选择 Google 账号',
|
|
513
548
|
placeholder: '',
|
|
514
|
-
options:
|
|
549
|
+
options: [
|
|
550
|
+
{ label: '添加新的 Google 账号', value: NEW_ACCOUNT, hint: '打开登录窗口' },
|
|
551
|
+
...accounts.map(a => ({
|
|
552
|
+
label: labelOf(a),
|
|
553
|
+
value: a.id,
|
|
554
|
+
hint: a.state === 'auth_required' ? '需要重新登录:会打开登录窗口' : ACCOUNT_STATES[a.state] || a.state || ''
|
|
555
|
+
}))
|
|
556
|
+
]
|
|
515
557
|
};
|
|
516
558
|
},
|
|
517
559
|
async authorize(inputs) {
|
|
518
|
-
const
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
async callback() {
|
|
526
|
-
let local;
|
|
527
|
-
try {
|
|
528
|
-
local = await ensureStudio({ proxy: opts.proxy, managementOnly: true });
|
|
529
|
-
const res = await studioAdmin(local, 'POST', `/api/accounts/${encodeURIComponent(chosen.id)}/login`, {}, { timeoutMs: LOGIN_TIMEOUT_MS });
|
|
530
|
-
if (res?.account?.state === 'auth_required') throw new Error(res.account.message || '账号仍然需要重新登录');
|
|
531
|
-
} catch (err) {
|
|
532
|
-
return { type: 'failed', error: `${labelOf(chosen)} 没有重新登录:${err.message}` };
|
|
533
|
-
}
|
|
534
|
-
return afterLogin(local);
|
|
535
|
-
}
|
|
536
|
-
};
|
|
560
|
+
const id = inputs?.account;
|
|
561
|
+
if (!id || id === NEW_ACCOUNT) return addAccount();
|
|
562
|
+
const local = await ensureStudio({ proxy: opts.proxy, managementOnly: true });
|
|
563
|
+
const chosen = (await studioAccounts(opts)).find(a => a.id === id);
|
|
564
|
+
if (!chosen) throw new Error(`本地 Google AI Studio 里没有启用的账号 ${id}`);
|
|
565
|
+
if (chosen.state === 'auth_required') return signInAgain(chosen);
|
|
566
|
+
return { url: '', method: 'auto', instructions: '', callback: async () => accountSignIn(local, chosen) };
|
|
537
567
|
}
|
|
538
568
|
},
|
|
539
569
|
{
|
|
@@ -614,7 +644,16 @@ export const AIStudioPlugin = async (_input, options = {}) => {
|
|
|
614
644
|
}
|
|
615
645
|
const enabled = (Array.isArray(accounts?.accounts) ? accounts.accounts : []).filter(a => a && a.enabled !== false);
|
|
616
646
|
const cooling = Array.isArray(cooldowns?.cooldowns) ? cooldowns.cooldowns : [];
|
|
617
|
-
|
|
647
|
+
const id = auth.metadata.account;
|
|
648
|
+
if (typeof id !== 'string' || !id) {
|
|
649
|
+
// A sign-in for the whole pool, as 0.5.0 made them
|
|
650
|
+
return { ...poolUsage(enabled, cooling), signIn: 'kept' };
|
|
651
|
+
}
|
|
652
|
+
const account = enabled.find(a => a.id === id);
|
|
653
|
+
if (!account) {
|
|
654
|
+
return { error: `本地 AI Studio 里已经没有这个账号(${auth.metadata.email || id}),可能被停用或删除了`, windows: [], signIn: 'kept' };
|
|
655
|
+
}
|
|
656
|
+
return { ...accountUsage(account, cooling), signIn: 'kept' };
|
|
618
657
|
}
|
|
619
658
|
},
|
|
620
659
|
provider: {
|
package/package.json
CHANGED