mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
fix lint/format issues
This commit is contained in:
@@ -136,7 +136,9 @@ const config = {
|
|||||||
bindCredentials: process.env.LDAP_BIND_PASSWORD || 'admin',
|
bindCredentials: process.env.LDAP_BIND_PASSWORD || 'admin',
|
||||||
searchBase: process.env.LDAP_SEARCH_BASE || 'dc=example,dc=com',
|
searchBase: process.env.LDAP_SEARCH_BASE || 'dc=example,dc=com',
|
||||||
searchFilter: process.env.LDAP_SEARCH_FILTER || '(uid={{username}})',
|
searchFilter: process.env.LDAP_SEARCH_FILTER || '(uid={{username}})',
|
||||||
searchAttributes: process.env.LDAP_SEARCH_ATTRIBUTES ? process.env.LDAP_SEARCH_ATTRIBUTES.split(',') : ['dn', 'uid', 'cn', 'mail', 'givenName', 'sn'],
|
searchAttributes: process.env.LDAP_SEARCH_ATTRIBUTES
|
||||||
|
? process.env.LDAP_SEARCH_ATTRIBUTES.split(',')
|
||||||
|
: ['dn', 'uid', 'cn', 'mail', 'givenName', 'sn'],
|
||||||
timeout: parseInt(process.env.LDAP_TIMEOUT) || 5000,
|
timeout: parseInt(process.env.LDAP_TIMEOUT) || 5000,
|
||||||
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT) || 10000,
|
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT) || 10000,
|
||||||
// TLS/SSL 配置
|
// TLS/SSL 配置
|
||||||
@@ -144,11 +146,17 @@ const config = {
|
|||||||
// 是否忽略证书错误 (用于自签名证书)
|
// 是否忽略证书错误 (用于自签名证书)
|
||||||
rejectUnauthorized: process.env.LDAP_TLS_REJECT_UNAUTHORIZED !== 'false', // 默认验证证书,设置为false则忽略
|
rejectUnauthorized: process.env.LDAP_TLS_REJECT_UNAUTHORIZED !== 'false', // 默认验证证书,设置为false则忽略
|
||||||
// CA证书文件路径 (可选,用于自定义CA证书)
|
// CA证书文件路径 (可选,用于自定义CA证书)
|
||||||
ca: process.env.LDAP_TLS_CA_FILE ? require('fs').readFileSync(process.env.LDAP_TLS_CA_FILE) : undefined,
|
ca: process.env.LDAP_TLS_CA_FILE
|
||||||
|
? require('fs').readFileSync(process.env.LDAP_TLS_CA_FILE)
|
||||||
|
: undefined,
|
||||||
// 客户端证书文件路径 (可选,用于双向认证)
|
// 客户端证书文件路径 (可选,用于双向认证)
|
||||||
cert: process.env.LDAP_TLS_CERT_FILE ? require('fs').readFileSync(process.env.LDAP_TLS_CERT_FILE) : undefined,
|
cert: process.env.LDAP_TLS_CERT_FILE
|
||||||
|
? require('fs').readFileSync(process.env.LDAP_TLS_CERT_FILE)
|
||||||
|
: undefined,
|
||||||
// 客户端私钥文件路径 (可选,用于双向认证)
|
// 客户端私钥文件路径 (可选,用于双向认证)
|
||||||
key: process.env.LDAP_TLS_KEY_FILE ? require('fs').readFileSync(process.env.LDAP_TLS_KEY_FILE) : undefined,
|
key: process.env.LDAP_TLS_KEY_FILE
|
||||||
|
? require('fs').readFileSync(process.env.LDAP_TLS_KEY_FILE)
|
||||||
|
: undefined,
|
||||||
// 服务器名称 (用于SNI,可选)
|
// 服务器名称 (用于SNI,可选)
|
||||||
servername: process.env.LDAP_TLS_SERVERNAME || undefined
|
servername: process.env.LDAP_TLS_SERVERNAME || undefined
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -272,11 +272,11 @@ function handleStreamResponse(upstreamResponse, clientResponse, options = {}) {
|
|||||||
let hasEnded = false
|
let hasEnded = false
|
||||||
let eventCount = 0
|
let eventCount = 0
|
||||||
const maxEvents = 10000 // 最大事件数量限制
|
const maxEvents = 10000 // 最大事件数量限制
|
||||||
|
|
||||||
// 专门用于保存最后几个chunks以提取usage数据
|
// 专门用于保存最后几个chunks以提取usage数据
|
||||||
let finalChunksBuffer = ''
|
let finalChunksBuffer = ''
|
||||||
const FINAL_CHUNKS_SIZE = 32 * 1024 // 32KB保留最终chunks
|
const FINAL_CHUNKS_SIZE = 32 * 1024 // 32KB保留最终chunks
|
||||||
let allParsedEvents = [] // 存储所有解析的事件用于最终usage提取
|
const allParsedEvents = [] // 存储所有解析的事件用于最终usage提取
|
||||||
|
|
||||||
// 设置响应头
|
// 设置响应头
|
||||||
clientResponse.setHeader('Content-Type', 'text/event-stream')
|
clientResponse.setHeader('Content-Type', 'text/event-stream')
|
||||||
@@ -314,7 +314,7 @@ function handleStreamResponse(upstreamResponse, clientResponse, options = {}) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const eventData = JSON.parse(jsonStr)
|
const eventData = JSON.parse(jsonStr)
|
||||||
|
|
||||||
// 保存所有成功解析的事件
|
// 保存所有成功解析的事件
|
||||||
allParsedEvents.push(eventData)
|
allParsedEvents.push(eventData)
|
||||||
|
|
||||||
@@ -324,14 +324,17 @@ function handleStreamResponse(upstreamResponse, clientResponse, options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 使用强化的usage提取函数
|
// 使用强化的usage提取函数
|
||||||
const { usageData: extractedUsage, actualModel: extractedModel } = extractUsageDataRobust(
|
const { usageData: extractedUsage, actualModel: extractedModel } =
|
||||||
eventData,
|
extractUsageDataRobust(
|
||||||
`stream-event-${isFromFinalBuffer ? 'final' : 'normal'}`
|
eventData,
|
||||||
)
|
`stream-event-${isFromFinalBuffer ? 'final' : 'normal'}`
|
||||||
|
)
|
||||||
|
|
||||||
if (extractedUsage && !usageData) {
|
if (extractedUsage && !usageData) {
|
||||||
usageData = extractedUsage
|
usageData = extractedUsage
|
||||||
if (extractedModel) actualModel = extractedModel
|
if (extractedModel) {
|
||||||
|
actualModel = extractedModel
|
||||||
|
}
|
||||||
logger.debug(`🎯 Stream usage captured via robust extraction`, {
|
logger.debug(`🎯 Stream usage captured via robust extraction`, {
|
||||||
isFromFinalBuffer,
|
isFromFinalBuffer,
|
||||||
usageData,
|
usageData,
|
||||||
@@ -358,7 +361,6 @@ function handleStreamResponse(upstreamResponse, clientResponse, options = {}) {
|
|||||||
logger.debug('🎯 Stream usage (backup method - top-level):', usageData)
|
logger.debug('🎯 Stream usage (backup method - top-level):', usageData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.debug('SSE parsing error (expected for incomplete chunks):', e.message)
|
logger.debug('SSE parsing error (expected for incomplete chunks):', e.message)
|
||||||
}
|
}
|
||||||
@@ -418,7 +420,9 @@ function handleStreamResponse(upstreamResponse, clientResponse, options = {}) {
|
|||||||
|
|
||||||
// 防止主缓冲区过大 - 但保持最后部分用于usage解析
|
// 防止主缓冲区过大 - 但保持最后部分用于usage解析
|
||||||
if (buffer.length > MAX_BUFFER_SIZE) {
|
if (buffer.length > MAX_BUFFER_SIZE) {
|
||||||
logger.warn(`Stream ${streamId} buffer exceeded limit, truncating main buffer but preserving final chunks`)
|
logger.warn(
|
||||||
|
`Stream ${streamId} buffer exceeded limit, truncating main buffer but preserving final chunks`
|
||||||
|
)
|
||||||
// 保留最后1/4而不是1/2,为usage数据留更多空间
|
// 保留最后1/4而不是1/2,为usage数据留更多空间
|
||||||
buffer = buffer.slice(-MAX_BUFFER_SIZE / 4)
|
buffer = buffer.slice(-MAX_BUFFER_SIZE / 4)
|
||||||
}
|
}
|
||||||
@@ -481,16 +485,18 @@ function handleStreamResponse(upstreamResponse, clientResponse, options = {}) {
|
|||||||
// 方法3: 从所有解析的事件中重新搜索usage
|
// 方法3: 从所有解析的事件中重新搜索usage
|
||||||
if (!usageData && allParsedEvents.length > 0) {
|
if (!usageData && allParsedEvents.length > 0) {
|
||||||
logger.debug('🔍 Searching through all parsed events for usage...')
|
logger.debug('🔍 Searching through all parsed events for usage...')
|
||||||
|
|
||||||
// 倒序查找,因为usage通常在最后
|
// 倒序查找,因为usage通常在最后
|
||||||
for (let i = allParsedEvents.length - 1; i >= 0; i--) {
|
for (let i = allParsedEvents.length - 1; i >= 0; i--) {
|
||||||
const { usageData: foundUsage, actualModel: foundModel } = extractUsageDataRobust(
|
const { usageData: foundUsage, actualModel: foundModel } = extractUsageDataRobust(
|
||||||
allParsedEvents[i],
|
allParsedEvents[i],
|
||||||
`final-event-scan-${i}`
|
`final-event-scan-${i}`
|
||||||
)
|
)
|
||||||
if (foundUsage) {
|
if (foundUsage) {
|
||||||
usageData = foundUsage
|
usageData = foundUsage
|
||||||
if (foundModel) actualModel = foundModel
|
if (foundModel) {
|
||||||
|
actualModel = foundModel
|
||||||
|
}
|
||||||
logger.debug(`🎯 Usage found in event ${i} during final scan!`)
|
logger.debug(`🎯 Usage found in event ${i} during final scan!`)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -505,8 +511,11 @@ function handleStreamResponse(upstreamResponse, clientResponse, options = {}) {
|
|||||||
lastEvent: allParsedEvents[allParsedEvents.length - 1],
|
lastEvent: allParsedEvents[allParsedEvents.length - 1],
|
||||||
eventCount: allParsedEvents.length
|
eventCount: allParsedEvents.length
|
||||||
}
|
}
|
||||||
|
|
||||||
const { usageData: combinedUsage } = extractUsageDataRobust(combinedData, 'combined-events')
|
const { usageData: combinedUsage } = extractUsageDataRobust(
|
||||||
|
combinedData,
|
||||||
|
'combined-events'
|
||||||
|
)
|
||||||
if (combinedUsage) {
|
if (combinedUsage) {
|
||||||
usageData = combinedUsage
|
usageData = combinedUsage
|
||||||
logger.debug('🎯 Usage found via combined events analysis!')
|
logger.debug('🎯 Usage found via combined events analysis!')
|
||||||
@@ -529,7 +538,7 @@ function handleStreamResponse(upstreamResponse, clientResponse, options = {}) {
|
|||||||
totalEvents: allParsedEvents.length,
|
totalEvents: allParsedEvents.length,
|
||||||
finalBufferSize: finalChunksBuffer.length,
|
finalBufferSize: finalChunksBuffer.length,
|
||||||
mainBufferSize: buffer.length,
|
mainBufferSize: buffer.length,
|
||||||
lastFewEvents: allParsedEvents.slice(-3).map(e => ({
|
lastFewEvents: allParsedEvents.slice(-3).map((e) => ({
|
||||||
type: e.type,
|
type: e.type,
|
||||||
hasUsage: !!e.usage,
|
hasUsage: !!e.usage,
|
||||||
hasResponse: !!e.response,
|
hasResponse: !!e.response,
|
||||||
@@ -610,35 +619,39 @@ function extractUsageDataRobust(responseData, context = 'unknown') {
|
|||||||
actualModel = responseData.model
|
actualModel = responseData.model
|
||||||
logger.debug('✅ Usage extracted via Strategy 1 (top-level)', { usageData, actualModel })
|
logger.debug('✅ Usage extracted via Strategy 1 (top-level)', { usageData, actualModel })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 策略 2: response.usage (Responses API)
|
// 策略 2: response.usage (Responses API)
|
||||||
else if (responseData?.response?.usage) {
|
else if (responseData?.response?.usage) {
|
||||||
usageData = responseData.response.usage
|
usageData = responseData.response.usage
|
||||||
actualModel = responseData.response.model || responseData.model
|
actualModel = responseData.response.model || responseData.model
|
||||||
logger.debug('✅ Usage extracted via Strategy 2 (response.usage)', { usageData, actualModel })
|
logger.debug('✅ Usage extracted via Strategy 2 (response.usage)', { usageData, actualModel })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 策略 3: 嵌套搜索 - 深度查找 usage 字段
|
// 策略 3: 嵌套搜索 - 深度查找 usage 字段
|
||||||
else {
|
else {
|
||||||
const findUsageRecursive = (obj, path = '') => {
|
const findUsageRecursive = (obj, path = '') => {
|
||||||
if (!obj || typeof obj !== 'object') return null
|
if (!obj || typeof obj !== 'object') {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(obj)) {
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
const currentPath = path ? `${path}.${key}` : key
|
const currentPath = path ? `${path}.${key}` : key
|
||||||
|
|
||||||
if (key === 'usage' && value && typeof value === 'object') {
|
if (key === 'usage' && value && typeof value === 'object') {
|
||||||
logger.debug(`✅ Usage found at path: ${currentPath}`, value)
|
logger.debug(`✅ Usage found at path: ${currentPath}`, value)
|
||||||
return { usage: value, path: currentPath }
|
return { usage: value, path: currentPath }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof value === 'object' && value !== null) {
|
if (typeof value === 'object' && value !== null) {
|
||||||
const nested = findUsageRecursive(value, currentPath)
|
const nested = findUsageRecursive(value, currentPath)
|
||||||
if (nested) return nested
|
if (nested) {
|
||||||
|
return nested
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const found = findUsageRecursive(responseData)
|
const found = findUsageRecursive(responseData)
|
||||||
if (found) {
|
if (found) {
|
||||||
usageData = found.usage
|
usageData = found.usage
|
||||||
@@ -650,14 +663,14 @@ function extractUsageDataRobust(responseData, context = 'unknown') {
|
|||||||
modelParent = modelParent?.[part]
|
modelParent = modelParent?.[part]
|
||||||
}
|
}
|
||||||
actualModel = modelParent?.model || responseData?.model
|
actualModel = modelParent?.model || responseData?.model
|
||||||
logger.debug('✅ Usage extracted via Strategy 3 (recursive)', {
|
logger.debug('✅ Usage extracted via Strategy 3 (recursive)', {
|
||||||
usageData,
|
usageData,
|
||||||
actualModel,
|
actualModel,
|
||||||
foundPath: found.path
|
foundPath: found.path
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 策略 4: 特殊响应格式处理
|
// 策略 4: 特殊响应格式处理
|
||||||
if (!usageData) {
|
if (!usageData) {
|
||||||
// 检查是否有 choices 数组,usage 可能在最后一个 choice 中
|
// 检查是否有 choices 数组,usage 可能在最后一个 choice 中
|
||||||
@@ -684,12 +697,11 @@ function extractUsageDataRobust(responseData, context = 'unknown') {
|
|||||||
} else {
|
} else {
|
||||||
logger.warn('❌ Failed to extract usage data', {
|
logger.warn('❌ Failed to extract usage data', {
|
||||||
context,
|
context,
|
||||||
responseDataStructure: JSON.stringify(responseData, null, 2).substring(0, 1000) + '...',
|
responseDataStructure: `${JSON.stringify(responseData, null, 2).substring(0, 1000)}...`,
|
||||||
availableKeys: Object.keys(responseData || {}),
|
availableKeys: Object.keys(responseData || {}),
|
||||||
responseSize: JSON.stringify(responseData || {}).length
|
responseSize: JSON.stringify(responseData || {}).length
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (extractionError) {
|
} catch (extractionError) {
|
||||||
logger.error('🚨 Error during usage extraction', {
|
logger.error('🚨 Error during usage extraction', {
|
||||||
context,
|
context,
|
||||||
|
|||||||
Reference in New Issue
Block a user