feat(config): add configurable max accounts limit (#156)

Adds `maxAccounts` configuration parameter to control the maximum number of Google accounts.

**Changes:**
- New config field `maxAccounts` (default: 10, range: 1-100)
- Settings page: slider control for adjusting limit
- Accounts page: counter badge (e.g., "8/10") with visual feedback
- Add button disabled when limit reached
- Server-side validation on account creation

**Breaking Changes:** None
This commit is contained in:
jgor20
2026-01-20 20:34:57 +00:00
committed by GitHub
parent 11f135ef32
commit e51e3ff56a
10 changed files with 76 additions and 4 deletions

View File

@@ -15,6 +15,7 @@ const DEFAULT_CONFIG = {
persistTokenCache: false,
defaultCooldownMs: 10000, // 10 seconds
maxWaitBeforeErrorMs: 120000, // 2 minutes
maxAccounts: 10, // Maximum number of accounts allowed
modelMapping: {},
// Account selection strategy configuration
accountSelection: {

View File

@@ -17,7 +17,7 @@ import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
import express from 'express';
import { getPublicConfig, saveConfig, config } from '../config.js';
import { DEFAULT_PORT, ACCOUNT_CONFIG_PATH } from '../constants.js';
import { DEFAULT_PORT, ACCOUNT_CONFIG_PATH, MAX_ACCOUNTS } from '../constants.js';
import { readClaudeConfig, updateClaudeConfig, replaceClaudeConfig, getClaudeConfigPath, readPresets, savePreset, deletePreset } from '../utils/claude-config.js';
import { logger } from '../utils/logger.js';
import { getAuthorizationUrl, completeOAuthFlow, startCallbackServer } from '../auth/oauth.js';
@@ -77,6 +77,7 @@ async function removeAccount(email) {
/**
* Add new account to config
* @throws {Error} If MAX_ACCOUNTS limit is reached (for new accounts only)
*/
async function addAccount(accountData) {
const { accounts, settings, activeIndex } = await loadAccounts(ACCOUNT_CONFIG_PATH);
@@ -95,6 +96,10 @@ async function addAccount(accountData) {
};
logger.info(`[WebUI] Account ${accountData.email} updated`);
} else {
// Check MAX_ACCOUNTS limit before adding new account
if (accounts.length >= MAX_ACCOUNTS) {
throw new Error(`Maximum of ${MAX_ACCOUNTS} accounts reached. Update maxAccounts in config to increase the limit.`);
}
// Add new account
accounts.push({
...accountData,
@@ -282,7 +287,7 @@ export function mountWebUI(app, dirname, accountManager) {
*/
app.post('/api/config', (req, res) => {
try {
const { debug, logLevel, maxRetries, retryBaseMs, retryMaxMs, persistTokenCache, defaultCooldownMs, maxWaitBeforeErrorMs, accountSelection } = req.body;
const { debug, logLevel, maxRetries, retryBaseMs, retryMaxMs, persistTokenCache, defaultCooldownMs, maxWaitBeforeErrorMs, maxAccounts, accountSelection } = req.body;
// Only allow updating specific fields (security)
const updates = {};
@@ -308,6 +313,9 @@ export function mountWebUI(app, dirname, accountManager) {
if (typeof maxWaitBeforeErrorMs === 'number' && maxWaitBeforeErrorMs >= 0 && maxWaitBeforeErrorMs <= 600000) {
updates.maxWaitBeforeErrorMs = maxWaitBeforeErrorMs;
}
if (typeof maxAccounts === 'number' && maxAccounts >= 1 && maxAccounts <= 100) {
updates.maxAccounts = maxAccounts;
}
// Account selection strategy validation
if (accountSelection && typeof accountSelection === 'object') {
const validStrategies = ['sticky', 'round-robin', 'hybrid'];