mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 21:17:30 +00:00
fix: 修复gemini-api账户共享池无法调度问题
This commit is contained in:
@@ -630,15 +630,22 @@ async function handleModels(req, res) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 选择账户获取模型列表
|
// 选择账户获取模型列表(允许 API 账户)
|
||||||
let account = null
|
let account = null
|
||||||
|
let isApiAccount = false
|
||||||
try {
|
try {
|
||||||
const accountSelection = await unifiedGeminiScheduler.selectAccountForApiKey(
|
const accountSelection = await unifiedGeminiScheduler.selectAccountForApiKey(
|
||||||
apiKeyData,
|
apiKeyData,
|
||||||
null,
|
null,
|
||||||
null
|
null,
|
||||||
|
{ allowApiAccounts: true }
|
||||||
)
|
)
|
||||||
|
isApiAccount = accountSelection.accountType === 'gemini-api'
|
||||||
|
if (isApiAccount) {
|
||||||
|
account = await geminiApiAccountService.getAccount(accountSelection.accountId)
|
||||||
|
} else {
|
||||||
account = await geminiAccountService.getAccount(accountSelection.accountId)
|
account = await geminiAccountService.getAccount(accountSelection.accountId)
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.warn('Failed to select Gemini account for models endpoint:', error)
|
logger.warn('Failed to select Gemini account for models endpoint:', error)
|
||||||
}
|
}
|
||||||
@@ -659,7 +666,45 @@ async function handleModels(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取模型列表
|
// 获取模型列表
|
||||||
const models = await getAvailableModels(account.accessToken, account.proxy)
|
let models
|
||||||
|
if (isApiAccount) {
|
||||||
|
// API Key 账户:使用 API Key 获取模型列表
|
||||||
|
const proxyConfig = parseProxyConfig(account)
|
||||||
|
try {
|
||||||
|
const apiUrl = `${account.baseUrl}/v1beta/models?key=${account.apiKey}`
|
||||||
|
const axiosConfig = {
|
||||||
|
method: 'GET',
|
||||||
|
url: apiUrl,
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
}
|
||||||
|
if (proxyConfig) {
|
||||||
|
const proxyHelper = new ProxyHelper()
|
||||||
|
axiosConfig.httpsAgent = proxyHelper.createProxyAgent(proxyConfig)
|
||||||
|
axiosConfig.httpAgent = proxyHelper.createProxyAgent(proxyConfig)
|
||||||
|
}
|
||||||
|
const response = await axios(axiosConfig)
|
||||||
|
models = (response.data.models || []).map((m) => ({
|
||||||
|
id: m.name?.replace('models/', '') || m.name,
|
||||||
|
object: 'model',
|
||||||
|
created: Date.now() / 1000,
|
||||||
|
owned_by: 'google'
|
||||||
|
}))
|
||||||
|
} catch (error) {
|
||||||
|
logger.warn('Failed to fetch models from Gemini API:', error.message)
|
||||||
|
// 返回默认模型列表
|
||||||
|
models = [
|
||||||
|
{
|
||||||
|
id: 'gemini-2.5-flash',
|
||||||
|
object: 'model',
|
||||||
|
created: Date.now() / 1000,
|
||||||
|
owned_by: 'google'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// OAuth 账户:使用 OAuth token 获取模型列表
|
||||||
|
models = await getAvailableModels(account.accessToken, account.proxy)
|
||||||
|
}
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
object: 'list',
|
object: 'list',
|
||||||
@@ -786,12 +831,36 @@ function handleSimpleEndpoint(apiMethod) {
|
|||||||
|
|
||||||
// 从路径参数或请求体中获取模型名
|
// 从路径参数或请求体中获取模型名
|
||||||
const requestedModel = req.body.model || req.params.modelName || 'gemini-2.5-flash'
|
const requestedModel = req.body.model || req.params.modelName || 'gemini-2.5-flash'
|
||||||
const { accountId } = await unifiedGeminiScheduler.selectAccountForApiKey(
|
const schedulerResult = await unifiedGeminiScheduler.selectAccountForApiKey(
|
||||||
req.apiKey,
|
req.apiKey,
|
||||||
sessionHash,
|
sessionHash,
|
||||||
requestedModel
|
requestedModel
|
||||||
)
|
)
|
||||||
|
const { accountId, accountType } = schedulerResult
|
||||||
|
|
||||||
|
// v1internal 路由只支持 OAuth 账户,不支持 API Key 账户
|
||||||
|
if (accountType === 'gemini-api') {
|
||||||
|
logger.error(
|
||||||
|
`❌ v1internal routes do not support Gemini API accounts. Account: ${accountId}`
|
||||||
|
)
|
||||||
|
return res.status(400).json({
|
||||||
|
error: {
|
||||||
|
message:
|
||||||
|
'This endpoint only supports Gemini OAuth accounts. Gemini API Key accounts are not compatible with v1internal format.',
|
||||||
|
type: 'invalid_account_type'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const account = await geminiAccountService.getAccount(accountId)
|
const account = await geminiAccountService.getAccount(accountId)
|
||||||
|
if (!account) {
|
||||||
|
return res.status(404).json({
|
||||||
|
error: {
|
||||||
|
message: 'Gemini account not found',
|
||||||
|
type: 'account_not_found'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
const { accessToken, refreshToken } = account
|
const { accessToken, refreshToken } = account
|
||||||
|
|
||||||
const version = req.path.includes('v1beta') ? 'v1beta' : 'v1internal'
|
const version = req.path.includes('v1beta') ? 'v1beta' : 'v1internal'
|
||||||
@@ -842,12 +911,34 @@ async function handleLoadCodeAssist(req, res) {
|
|||||||
|
|
||||||
// 从路径参数或请求体中获取模型名
|
// 从路径参数或请求体中获取模型名
|
||||||
const requestedModel = req.body.model || req.params.modelName || 'gemini-2.5-flash'
|
const requestedModel = req.body.model || req.params.modelName || 'gemini-2.5-flash'
|
||||||
const { accountId } = await unifiedGeminiScheduler.selectAccountForApiKey(
|
const schedulerResult = await unifiedGeminiScheduler.selectAccountForApiKey(
|
||||||
req.apiKey,
|
req.apiKey,
|
||||||
sessionHash,
|
sessionHash,
|
||||||
requestedModel
|
requestedModel
|
||||||
)
|
)
|
||||||
|
const { accountId, accountType } = schedulerResult
|
||||||
|
|
||||||
|
// v1internal 路由只支持 OAuth 账户,不支持 API Key 账户
|
||||||
|
if (accountType === 'gemini-api') {
|
||||||
|
logger.error(`❌ v1internal routes do not support Gemini API accounts. Account: ${accountId}`)
|
||||||
|
return res.status(400).json({
|
||||||
|
error: {
|
||||||
|
message:
|
||||||
|
'This endpoint only supports Gemini OAuth accounts. Gemini API Key accounts are not compatible with v1internal format.',
|
||||||
|
type: 'invalid_account_type'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const account = await geminiAccountService.getAccount(accountId)
|
const account = await geminiAccountService.getAccount(accountId)
|
||||||
|
if (!account) {
|
||||||
|
return res.status(404).json({
|
||||||
|
error: {
|
||||||
|
message: 'Gemini account not found',
|
||||||
|
type: 'account_not_found'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
const { accessToken, refreshToken, projectId } = account
|
const { accessToken, refreshToken, projectId } = account
|
||||||
|
|
||||||
const { metadata, cloudaicompanionProject } = req.body
|
const { metadata, cloudaicompanionProject } = req.body
|
||||||
@@ -919,12 +1010,34 @@ async function handleOnboardUser(req, res) {
|
|||||||
|
|
||||||
// 从路径参数或请求体中获取模型名
|
// 从路径参数或请求体中获取模型名
|
||||||
const requestedModel = req.body.model || req.params.modelName || 'gemini-2.5-flash'
|
const requestedModel = req.body.model || req.params.modelName || 'gemini-2.5-flash'
|
||||||
const { accountId } = await unifiedGeminiScheduler.selectAccountForApiKey(
|
const schedulerResult = await unifiedGeminiScheduler.selectAccountForApiKey(
|
||||||
req.apiKey,
|
req.apiKey,
|
||||||
sessionHash,
|
sessionHash,
|
||||||
requestedModel
|
requestedModel
|
||||||
)
|
)
|
||||||
|
const { accountId, accountType } = schedulerResult
|
||||||
|
|
||||||
|
// v1internal 路由只支持 OAuth 账户,不支持 API Key 账户
|
||||||
|
if (accountType === 'gemini-api') {
|
||||||
|
logger.error(`❌ v1internal routes do not support Gemini API accounts. Account: ${accountId}`)
|
||||||
|
return res.status(400).json({
|
||||||
|
error: {
|
||||||
|
message:
|
||||||
|
'This endpoint only supports Gemini OAuth accounts. Gemini API Key accounts are not compatible with v1internal format.',
|
||||||
|
type: 'invalid_account_type'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const account = await geminiAccountService.getAccount(accountId)
|
const account = await geminiAccountService.getAccount(accountId)
|
||||||
|
if (!account) {
|
||||||
|
return res.status(404).json({
|
||||||
|
error: {
|
||||||
|
message: 'Gemini account not found',
|
||||||
|
type: 'account_not_found'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
const { accessToken, refreshToken, projectId } = account
|
const { accessToken, refreshToken, projectId } = account
|
||||||
|
|
||||||
const version = req.path.includes('v1beta') ? 'v1beta' : 'v1internal'
|
const version = req.path.includes('v1beta') ? 'v1beta' : 'v1internal'
|
||||||
@@ -1013,31 +1126,93 @@ async function handleCountTokens(req, res) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用统一调度选择账号
|
// 使用统一调度选择账号(允许 API 账户)
|
||||||
const { accountId } = await unifiedGeminiScheduler.selectAccountForApiKey(
|
const schedulerResult = await unifiedGeminiScheduler.selectAccountForApiKey(
|
||||||
req.apiKey,
|
req.apiKey,
|
||||||
sessionHash,
|
sessionHash,
|
||||||
model
|
model,
|
||||||
|
{ allowApiAccounts: true }
|
||||||
)
|
)
|
||||||
const account = await geminiAccountService.getAccount(accountId)
|
const { accountId, accountType } = schedulerResult
|
||||||
const { accessToken, refreshToken } = account
|
const isApiAccount = accountType === 'gemini-api'
|
||||||
|
|
||||||
const version = req.path.includes('v1beta') ? 'v1beta' : 'v1internal'
|
let account
|
||||||
logger.info(`CountTokens request (${version})`, {
|
if (isApiAccount) {
|
||||||
|
account = await geminiApiAccountService.getAccount(accountId)
|
||||||
|
} else {
|
||||||
|
account = await geminiAccountService.getAccount(accountId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!account) {
|
||||||
|
return res.status(404).json({
|
||||||
|
error: {
|
||||||
|
message: `${isApiAccount ? 'Gemini API' : 'Gemini'} account not found`,
|
||||||
|
type: 'account_not_found'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const version = req.path.includes('v1beta') ? 'v1beta' : 'v1'
|
||||||
|
logger.info(
|
||||||
|
`CountTokens request (${version}) - ${isApiAccount ? 'API Key' : 'OAuth'} Account`,
|
||||||
|
{
|
||||||
model,
|
model,
|
||||||
contentsLength: contents.length,
|
contentsLength: contents.length,
|
||||||
|
accountId,
|
||||||
apiKeyId: req.apiKey?.id || 'unknown'
|
apiKeyId: req.apiKey?.id || 'unknown'
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// 解析账户的代理配置
|
// 解析账户的代理配置
|
||||||
const proxyConfig = parseProxyConfig(account)
|
const proxyConfig = parseProxyConfig(account)
|
||||||
|
|
||||||
const client = await geminiAccountService.getOauthClient(accessToken, refreshToken, proxyConfig)
|
let response
|
||||||
const response = await geminiAccountService.countTokens(client, contents, model, proxyConfig)
|
if (isApiAccount) {
|
||||||
|
// API Key 账户:直接使用 API Key 请求
|
||||||
|
const modelPath = model.startsWith('models/') ? model : `models/${model}`
|
||||||
|
const apiUrl = `${account.baseUrl}/v1beta/${modelPath}:countTokens?key=${account.apiKey}`
|
||||||
|
|
||||||
|
const axiosConfig = {
|
||||||
|
method: 'POST',
|
||||||
|
url: apiUrl,
|
||||||
|
data: { contents },
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proxyConfig) {
|
||||||
|
const proxyHelper = new ProxyHelper()
|
||||||
|
axiosConfig.httpsAgent = proxyHelper.createProxyAgent(proxyConfig)
|
||||||
|
axiosConfig.httpAgent = proxyHelper.createProxyAgent(proxyConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const apiResponse = await axios(axiosConfig)
|
||||||
|
response = {
|
||||||
|
totalTokens: apiResponse.data.totalTokens || 0,
|
||||||
|
totalBillableCharacters: apiResponse.data.totalBillableCharacters || 0,
|
||||||
|
...apiResponse.data
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Gemini API countTokens request failed:', {
|
||||||
|
status: error.response?.status,
|
||||||
|
data: error.response?.data
|
||||||
|
})
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// OAuth 账户
|
||||||
|
const { accessToken, refreshToken } = account
|
||||||
|
const client = await geminiAccountService.getOauthClient(
|
||||||
|
accessToken,
|
||||||
|
refreshToken,
|
||||||
|
proxyConfig
|
||||||
|
)
|
||||||
|
response = await geminiAccountService.countTokens(client, contents, model, proxyConfig)
|
||||||
|
}
|
||||||
|
|
||||||
res.json(response)
|
res.json(response)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const version = req.path.includes('v1beta') ? 'v1beta' : 'v1internal'
|
const version = req.path.includes('v1beta') ? 'v1beta' : 'v1'
|
||||||
logger.error(`Error in countTokens endpoint (${version})`, { error: error.message })
|
logger.error(`Error in countTokens endpoint (${version})`, { error: error.message })
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
error: {
|
error: {
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ class UnifiedGeminiScheduler {
|
|||||||
return schedulable !== false && schedulable !== 'false'
|
return schedulable !== false && schedulable !== 'false'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 🔧 辅助方法:检查账户是否激活(兼容字符串和布尔值)
|
||||||
|
_isActive(isActive) {
|
||||||
|
// 兼容布尔值 true 和字符串 'true'
|
||||||
|
return isActive === true || isActive === 'true'
|
||||||
|
}
|
||||||
|
|
||||||
// 🎯 统一调度Gemini账号
|
// 🎯 统一调度Gemini账号
|
||||||
async selectAccountForApiKey(
|
async selectAccountForApiKey(
|
||||||
apiKeyData,
|
apiKeyData,
|
||||||
@@ -35,7 +41,11 @@ class UnifiedGeminiScheduler {
|
|||||||
if (apiKeyData.geminiAccountId.startsWith('api:')) {
|
if (apiKeyData.geminiAccountId.startsWith('api:')) {
|
||||||
const accountId = apiKeyData.geminiAccountId.replace('api:', '')
|
const accountId = apiKeyData.geminiAccountId.replace('api:', '')
|
||||||
const boundAccount = await geminiApiAccountService.getAccount(accountId)
|
const boundAccount = await geminiApiAccountService.getAccount(accountId)
|
||||||
if (boundAccount && boundAccount.isActive === 'true' && boundAccount.status !== 'error') {
|
if (
|
||||||
|
boundAccount &&
|
||||||
|
this._isActive(boundAccount.isActive) &&
|
||||||
|
boundAccount.status !== 'error'
|
||||||
|
) {
|
||||||
logger.info(
|
logger.info(
|
||||||
`🎯 Using bound Gemini-API account: ${boundAccount.name} (${accountId}) for API key ${apiKeyData.name}`
|
`🎯 Using bound Gemini-API account: ${boundAccount.name} (${accountId}) for API key ${apiKeyData.name}`
|
||||||
)
|
)
|
||||||
@@ -68,7 +78,11 @@ class UnifiedGeminiScheduler {
|
|||||||
// 普通 Gemini OAuth 专属账户
|
// 普通 Gemini OAuth 专属账户
|
||||||
else {
|
else {
|
||||||
const boundAccount = await geminiAccountService.getAccount(apiKeyData.geminiAccountId)
|
const boundAccount = await geminiAccountService.getAccount(apiKeyData.geminiAccountId)
|
||||||
if (boundAccount && boundAccount.isActive === 'true' && boundAccount.status !== 'error') {
|
if (
|
||||||
|
boundAccount &&
|
||||||
|
this._isActive(boundAccount.isActive) &&
|
||||||
|
boundAccount.status !== 'error'
|
||||||
|
) {
|
||||||
logger.info(
|
logger.info(
|
||||||
`🎯 Using bound dedicated Gemini account: ${boundAccount.name} (${apiKeyData.geminiAccountId}) for API key ${apiKeyData.name}`
|
`🎯 Using bound dedicated Gemini account: ${boundAccount.name} (${apiKeyData.geminiAccountId}) for API key ${apiKeyData.name}`
|
||||||
)
|
)
|
||||||
@@ -184,7 +198,11 @@ class UnifiedGeminiScheduler {
|
|||||||
if (apiKeyData.geminiAccountId.startsWith('api:')) {
|
if (apiKeyData.geminiAccountId.startsWith('api:')) {
|
||||||
const accountId = apiKeyData.geminiAccountId.replace('api:', '')
|
const accountId = apiKeyData.geminiAccountId.replace('api:', '')
|
||||||
const boundAccount = await geminiApiAccountService.getAccount(accountId)
|
const boundAccount = await geminiApiAccountService.getAccount(accountId)
|
||||||
if (boundAccount && boundAccount.isActive === 'true' && boundAccount.status !== 'error') {
|
if (
|
||||||
|
boundAccount &&
|
||||||
|
this._isActive(boundAccount.isActive) &&
|
||||||
|
boundAccount.status !== 'error'
|
||||||
|
) {
|
||||||
const isRateLimited = await this.isAccountRateLimited(accountId)
|
const isRateLimited = await this.isAccountRateLimited(accountId)
|
||||||
if (!isRateLimited) {
|
if (!isRateLimited) {
|
||||||
// 检查模型支持
|
// 检查模型支持
|
||||||
@@ -231,7 +249,11 @@ class UnifiedGeminiScheduler {
|
|||||||
// 普通 Gemini OAuth 账户
|
// 普通 Gemini OAuth 账户
|
||||||
else if (!apiKeyData.geminiAccountId.startsWith('group:')) {
|
else if (!apiKeyData.geminiAccountId.startsWith('group:')) {
|
||||||
const boundAccount = await geminiAccountService.getAccount(apiKeyData.geminiAccountId)
|
const boundAccount = await geminiAccountService.getAccount(apiKeyData.geminiAccountId)
|
||||||
if (boundAccount && boundAccount.isActive === 'true' && boundAccount.status !== 'error') {
|
if (
|
||||||
|
boundAccount &&
|
||||||
|
this._isActive(boundAccount.isActive) &&
|
||||||
|
boundAccount.status !== 'error'
|
||||||
|
) {
|
||||||
const isRateLimited = await this.isAccountRateLimited(boundAccount.id)
|
const isRateLimited = await this.isAccountRateLimited(boundAccount.id)
|
||||||
if (!isRateLimited) {
|
if (!isRateLimited) {
|
||||||
// 检查模型支持
|
// 检查模型支持
|
||||||
@@ -276,7 +298,7 @@ class UnifiedGeminiScheduler {
|
|||||||
const geminiAccounts = await geminiAccountService.getAllAccounts()
|
const geminiAccounts = await geminiAccountService.getAllAccounts()
|
||||||
for (const account of geminiAccounts) {
|
for (const account of geminiAccounts) {
|
||||||
if (
|
if (
|
||||||
account.isActive === 'true' &&
|
this._isActive(account.isActive) &&
|
||||||
account.status !== 'error' &&
|
account.status !== 'error' &&
|
||||||
(account.accountType === 'shared' || !account.accountType) && // 兼容旧数据
|
(account.accountType === 'shared' || !account.accountType) && // 兼容旧数据
|
||||||
this._isSchedulable(account.schedulable)
|
this._isSchedulable(account.schedulable)
|
||||||
@@ -326,7 +348,7 @@ class UnifiedGeminiScheduler {
|
|||||||
const geminiApiAccounts = await geminiApiAccountService.getAllAccounts()
|
const geminiApiAccounts = await geminiApiAccountService.getAllAccounts()
|
||||||
for (const account of geminiApiAccounts) {
|
for (const account of geminiApiAccounts) {
|
||||||
if (
|
if (
|
||||||
account.isActive === 'true' &&
|
this._isActive(account.isActive) &&
|
||||||
account.status !== 'error' &&
|
account.status !== 'error' &&
|
||||||
(account.accountType === 'shared' || !account.accountType) &&
|
(account.accountType === 'shared' || !account.accountType) &&
|
||||||
this._isSchedulable(account.schedulable)
|
this._isSchedulable(account.schedulable)
|
||||||
@@ -386,7 +408,7 @@ class UnifiedGeminiScheduler {
|
|||||||
try {
|
try {
|
||||||
if (accountType === 'gemini') {
|
if (accountType === 'gemini') {
|
||||||
const account = await geminiAccountService.getAccount(accountId)
|
const account = await geminiAccountService.getAccount(accountId)
|
||||||
if (!account || account.isActive !== 'true' || account.status === 'error') {
|
if (!account || !this._isActive(account.isActive) || account.status === 'error') {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// 检查是否可调度
|
// 检查是否可调度
|
||||||
@@ -397,7 +419,7 @@ class UnifiedGeminiScheduler {
|
|||||||
return !(await this.isAccountRateLimited(accountId))
|
return !(await this.isAccountRateLimited(accountId))
|
||||||
} else if (accountType === 'gemini-api') {
|
} else if (accountType === 'gemini-api') {
|
||||||
const account = await geminiApiAccountService.getAccount(accountId)
|
const account = await geminiApiAccountService.getAccount(accountId)
|
||||||
if (!account || account.isActive !== 'true' || account.status === 'error') {
|
if (!account || !this._isActive(account.isActive) || account.status === 'error') {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// 检查是否可调度
|
// 检查是否可调度
|
||||||
@@ -643,7 +665,7 @@ class UnifiedGeminiScheduler {
|
|||||||
|
|
||||||
// 检查账户是否可用
|
// 检查账户是否可用
|
||||||
if (
|
if (
|
||||||
account.isActive === 'true' &&
|
this._isActive(account.isActive) &&
|
||||||
account.status !== 'error' &&
|
account.status !== 'error' &&
|
||||||
this._isSchedulable(account.schedulable)
|
this._isSchedulable(account.schedulable)
|
||||||
) {
|
) {
|
||||||
|
|||||||
Reference in New Issue
Block a user