use proxy if configured in Gemini OAuth requests

This commit is contained in:
Feng Yue
2025-08-31 01:00:49 +08:00
parent dc3d311def
commit 1762669de4

View File

@@ -138,11 +138,19 @@ function createOAuth2Client(redirectUri = null, proxyConfig = null) {
return new OAuth2Client(clientOptions) return new OAuth2Client(clientOptions)
} }
// 生成授权 URL (支持 PKCE) // 生成授权 URL (支持 PKCE 和代理)
async function generateAuthUrl(state = null, redirectUri = null) { async function generateAuthUrl(state = null, redirectUri = null, proxyConfig = null) {
// 使用新的 redirect URI // 使用新的 redirect URI
const finalRedirectUri = redirectUri || 'https://codeassist.google.com/authcode' const finalRedirectUri = redirectUri || 'https://codeassist.google.com/authcode'
const oAuth2Client = createOAuth2Client(finalRedirectUri) const oAuth2Client = createOAuth2Client(finalRedirectUri, proxyConfig)
if (proxyConfig) {
logger.info(
`🌐 Using proxy for Gemini auth URL generation: ${ProxyHelper.getProxyDescription(proxyConfig)}`
)
} else {
logger.debug('🌐 No proxy configured for Gemini auth URL generation')
}
// 生成 PKCE code verifier // 生成 PKCE code verifier
const codeVerifier = await oAuth2Client.generateCodeVerifierAsync() const codeVerifier = await oAuth2Client.generateCodeVerifierAsync()
@@ -965,12 +973,10 @@ async function getAccountRateLimitInfo(accountId) {
} }
} }
// 获取配置的OAuth客户端 - 参考GeminiCliSimulator的getOauthClient方法 // 获取配置的OAuth客户端 - 参考GeminiCliSimulator的getOauthClient方法(支持代理)
async function getOauthClient(accessToken, refreshToken) { async function getOauthClient(accessToken, refreshToken, proxyConfig = null) {
const client = new OAuth2Client({ const client = createOAuth2Client(null, proxyConfig)
clientId: OAUTH_CLIENT_ID,
clientSecret: OAUTH_CLIENT_SECRET
})
const creds = { const creds = {
access_token: accessToken, access_token: accessToken,
refresh_token: refreshToken, refresh_token: refreshToken,
@@ -980,6 +986,14 @@ async function getOauthClient(accessToken, refreshToken) {
expiry_date: 1754269905646 expiry_date: 1754269905646
} }
if (proxyConfig) {
logger.info(
`🌐 Using proxy for Gemini OAuth client: ${ProxyHelper.getProxyDescription(proxyConfig)}`
)
} else {
logger.debug('🌐 No proxy configured for Gemini OAuth client')
}
// 设置凭据 // 设置凭据
client.setCredentials(creds) client.setCredentials(creds)
@@ -996,8 +1010,8 @@ async function getOauthClient(accessToken, refreshToken) {
return client return client
} }
// 调用 Google Code Assist API 的 loadCodeAssist 方法 // 调用 Google Code Assist API 的 loadCodeAssist 方法(支持代理)
async function loadCodeAssist(client, projectId = null) { async function loadCodeAssist(client, projectId = null, proxyConfig = null) {
const axios = require('axios') const axios = require('axios')
const CODE_ASSIST_ENDPOINT = 'https://cloudcode-pa.googleapis.com' const CODE_ASSIST_ENDPOINT = 'https://cloudcode-pa.googleapis.com'
const CODE_ASSIST_API_VERSION = 'v1internal' const CODE_ASSIST_API_VERSION = 'v1internal'
@@ -1017,7 +1031,7 @@ async function loadCodeAssist(client, projectId = null) {
metadata: clientMetadata metadata: clientMetadata
} }
const response = await axios({ const axiosConfig = {
url: `${CODE_ASSIST_ENDPOINT}/${CODE_ASSIST_API_VERSION}:loadCodeAssist`, url: `${CODE_ASSIST_ENDPOINT}/${CODE_ASSIST_API_VERSION}:loadCodeAssist`,
method: 'POST', method: 'POST',
headers: { headers: {
@@ -1026,7 +1040,20 @@ async function loadCodeAssist(client, projectId = null) {
}, },
data: request, data: request,
timeout: 30000 timeout: 30000
}) }
// 添加代理配置
const proxyAgent = ProxyHelper.createProxyAgent(proxyConfig)
if (proxyAgent) {
axiosConfig.httpsAgent = proxyAgent
logger.info(
`🌐 Using proxy for Gemini loadCodeAssist: ${ProxyHelper.getProxyDescription(proxyConfig)}`
)
} else {
logger.debug('🌐 No proxy configured for Gemini loadCodeAssist')
}
const response = await axios(axiosConfig)
logger.info('📋 loadCodeAssist API调用成功') logger.info('📋 loadCodeAssist API调用成功')
return response.data return response.data
@@ -1059,8 +1086,8 @@ function getOnboardTier(loadRes) {
} }
} }
// 调用 Google Code Assist API 的 onboardUser 方法(包含轮询逻辑) // 调用 Google Code Assist API 的 onboardUser 方法(包含轮询逻辑,支持代理
async function onboardUser(client, tierId, projectId, clientMetadata) { async function onboardUser(client, tierId, projectId, clientMetadata, proxyConfig = null) {
const axios = require('axios') const axios = require('axios')
const CODE_ASSIST_ENDPOINT = 'https://cloudcode-pa.googleapis.com' const CODE_ASSIST_ENDPOINT = 'https://cloudcode-pa.googleapis.com'
const CODE_ASSIST_API_VERSION = 'v1internal' const CODE_ASSIST_API_VERSION = 'v1internal'
@@ -1073,6 +1100,29 @@ async function onboardUser(client, tierId, projectId, clientMetadata) {
metadata: clientMetadata metadata: clientMetadata
} }
// 创建基础axios配置
const baseAxiosConfig = {
url: `${CODE_ASSIST_ENDPOINT}/${CODE_ASSIST_API_VERSION}:onboardUser`,
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
data: onboardReq,
timeout: 30000
}
// 添加代理配置
const proxyAgent = ProxyHelper.createProxyAgent(proxyConfig)
if (proxyAgent) {
baseAxiosConfig.httpsAgent = proxyAgent
logger.info(
`🌐 Using proxy for Gemini onboardUser: ${ProxyHelper.getProxyDescription(proxyConfig)}`
)
} else {
logger.debug('🌐 No proxy configured for Gemini onboardUser')
}
logger.info('📋 开始onboardUser API调用', { logger.info('📋 开始onboardUser API调用', {
tierId, tierId,
projectId, projectId,
@@ -1081,16 +1131,7 @@ async function onboardUser(client, tierId, projectId, clientMetadata) {
}) })
// 轮询onboardUser直到长运行操作完成 // 轮询onboardUser直到长运行操作完成
let lroRes = await axios({ let lroRes = await axios(baseAxiosConfig)
url: `${CODE_ASSIST_ENDPOINT}/${CODE_ASSIST_API_VERSION}:onboardUser`,
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
data: onboardReq,
timeout: 30000
})
let attempts = 0 let attempts = 0
const maxAttempts = 12 // 最多等待1分钟5秒 * 12次 const maxAttempts = 12 // 最多等待1分钟5秒 * 12次
@@ -1099,17 +1140,7 @@ async function onboardUser(client, tierId, projectId, clientMetadata) {
logger.info(`⏳ 等待onboardUser完成... (${attempts + 1}/${maxAttempts})`) logger.info(`⏳ 等待onboardUser完成... (${attempts + 1}/${maxAttempts})`)
await new Promise((resolve) => setTimeout(resolve, 5000)) await new Promise((resolve) => setTimeout(resolve, 5000))
lroRes = await axios({ lroRes = await axios(baseAxiosConfig)
url: `${CODE_ASSIST_ENDPOINT}/${CODE_ASSIST_API_VERSION}:onboardUser`,
method: 'POST',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
data: onboardReq,
timeout: 30000
})
attempts++ attempts++
} }
@@ -1121,8 +1152,13 @@ async function onboardUser(client, tierId, projectId, clientMetadata) {
return lroRes.data return lroRes.data
} }
// 完整的用户设置流程 - 参考setup.ts的逻辑 // 完整的用户设置流程 - 参考setup.ts的逻辑(支持代理)
async function setupUser(client, initialProjectId = null, clientMetadata = null) { async function setupUser(
client,
initialProjectId = null,
clientMetadata = null,
proxyConfig = null
) {
logger.info('🚀 setupUser 开始', { initialProjectId, hasClientMetadata: !!clientMetadata }) logger.info('🚀 setupUser 开始', { initialProjectId, hasClientMetadata: !!clientMetadata })
let projectId = initialProjectId || process.env.GOOGLE_CLOUD_PROJECT || null let projectId = initialProjectId || process.env.GOOGLE_CLOUD_PROJECT || null
@@ -1141,7 +1177,7 @@ async function setupUser(client, initialProjectId = null, clientMetadata = null)
// 调用loadCodeAssist // 调用loadCodeAssist
logger.info('📞 调用 loadCodeAssist...') logger.info('📞 调用 loadCodeAssist...')
const loadRes = await loadCodeAssist(client, projectId) const loadRes = await loadCodeAssist(client, projectId, proxyConfig)
logger.info('✅ loadCodeAssist 完成', { logger.info('✅ loadCodeAssist 完成', {
hasCloudaicompanionProject: !!loadRes.cloudaicompanionProject hasCloudaicompanionProject: !!loadRes.cloudaicompanionProject
}) })
@@ -1164,7 +1200,7 @@ async function setupUser(client, initialProjectId = null, clientMetadata = null)
// 调用onboardUser // 调用onboardUser
logger.info('📞 调用 onboardUser...', { tierId: tier.id, projectId }) logger.info('📞 调用 onboardUser...', { tierId: tier.id, projectId })
const lroRes = await onboardUser(client, tier.id, projectId, clientMetadata) const lroRes = await onboardUser(client, tier.id, projectId, clientMetadata, proxyConfig)
logger.info('✅ onboardUser 完成', { hasDone: !!lroRes.done, hasResponse: !!lroRes.response }) logger.info('✅ onboardUser 完成', { hasDone: !!lroRes.done, hasResponse: !!lroRes.response })
const result = { const result = {
@@ -1178,8 +1214,8 @@ async function setupUser(client, initialProjectId = null, clientMetadata = null)
return result return result
} }
// 调用 Code Assist API 计算 token 数量 // 调用 Code Assist API 计算 token 数量(支持代理)
async function countTokens(client, contents, model = 'gemini-2.0-flash-exp') { async function countTokens(client, contents, model = 'gemini-2.0-flash-exp', proxyConfig = null) {
const axios = require('axios') const axios = require('axios')
const CODE_ASSIST_ENDPOINT = 'https://cloudcode-pa.googleapis.com' const CODE_ASSIST_ENDPOINT = 'https://cloudcode-pa.googleapis.com'
const CODE_ASSIST_API_VERSION = 'v1internal' const CODE_ASSIST_API_VERSION = 'v1internal'
@@ -1196,7 +1232,7 @@ async function countTokens(client, contents, model = 'gemini-2.0-flash-exp') {
logger.info('📊 countTokens API调用开始', { model, contentsLength: contents.length }) logger.info('📊 countTokens API调用开始', { model, contentsLength: contents.length })
const response = await axios({ const axiosConfig = {
url: `${CODE_ASSIST_ENDPOINT}/${CODE_ASSIST_API_VERSION}:countTokens`, url: `${CODE_ASSIST_ENDPOINT}/${CODE_ASSIST_API_VERSION}:countTokens`,
method: 'POST', method: 'POST',
headers: { headers: {
@@ -1205,7 +1241,20 @@ async function countTokens(client, contents, model = 'gemini-2.0-flash-exp') {
}, },
data: request, data: request,
timeout: 30000 timeout: 30000
}) }
// 添加代理配置
const proxyAgent = ProxyHelper.createProxyAgent(proxyConfig)
if (proxyAgent) {
axiosConfig.httpsAgent = proxyAgent
logger.info(
`🌐 Using proxy for Gemini countTokens: ${ProxyHelper.getProxyDescription(proxyConfig)}`
)
} else {
logger.debug('🌐 No proxy configured for Gemini countTokens')
}
const response = await axios(axiosConfig)
logger.info('✅ countTokens API调用成功', { totalTokens: response.data.totalTokens }) logger.info('✅ countTokens API调用成功', { totalTokens: response.data.totalTokens })
return response.data return response.data