(email, password)
| 477 | * so the background renewal loop in checkAndRefreshTokens picks it up. |
| 478 | */ |
| 479 | export async function addAccountByEmail(email, password) { |
| 480 | if (!email || !password) { |
| 481 | throw new Error('email and password required'); |
| 482 | } |
| 483 | const emailKey = String(email).trim().toLowerCase(); |
| 484 | const { windsurfLogin } = await import('./dashboard/windsurf-login.js'); |
| 485 | const result = await windsurfLogin(email, password, null); |
| 486 | if (!result?.apiKey) { |
| 487 | throw new Error('Login succeeded but no apiKey returned'); |
| 488 | } |
| 489 | const label = result.name || email; |
| 490 | const existingByEmail = accounts.find(a => String(a.email || '').trim().toLowerCase() === emailKey); |
| 491 | const account = existingByEmail || addAccountByKey(result.apiKey, label); |
| 492 | if (existingByEmail) { |
| 493 | account.apiKey = result.apiKey; |
| 494 | if (account.status === 'error') account.status = 'active'; |
| 495 | account.errorCount = 0; |
| 496 | } |
| 497 | if (account.email !== label) { |
| 498 | account.email = label; |
| 499 | } |
| 500 | account.method = 'email'; |
| 501 | if (result.apiServerUrl && !account.apiServerUrl) { |
| 502 | account.apiServerUrl = result.apiServerUrl; |
| 503 | } |
| 504 | if (result.refreshToken || result.idToken) { |
| 505 | setAccountTokens(account.id, { |
| 506 | refreshToken: result.refreshToken || '', |
| 507 | idToken: result.idToken || '', |
| 508 | }); |
| 509 | } |
| 510 | saveAccounts(); |
| 511 | log.info(`Account added via email: ${safeAccountRef(account)}`); |
| 512 | return account; |
| 513 | } |
| 514 | |
| 515 | /** |
| 516 | * Per-account blocklist: hide specific models from this account so the |
no test coverage detected