|
|
const path = require('path') |
|
|
require('dotenv').config() |
|
|
|
|
|
const config = { |
|
|
|
|
|
server: { |
|
|
port: parseInt(process.env.PORT) || 3000, |
|
|
host: process.env.HOST || '0.0.0.0', |
|
|
nodeEnv: process.env.NODE_ENV || 'development', |
|
|
trustProxy: process.env.TRUST_PROXY === 'true' |
|
|
}, |
|
|
|
|
|
|
|
|
security: { |
|
|
jwtSecret: process.env.JWT_SECRET || 'CHANGE-THIS-JWT-SECRET-IN-PRODUCTION', |
|
|
adminSessionTimeout: parseInt(process.env.ADMIN_SESSION_TIMEOUT) || 86400000, |
|
|
apiKeyPrefix: process.env.API_KEY_PREFIX || 'cr_', |
|
|
encryptionKey: process.env.ENCRYPTION_KEY || 'CHANGE-THIS-32-CHARACTER-KEY-NOW' |
|
|
}, |
|
|
|
|
|
|
|
|
redis: { |
|
|
host: process.env.REDIS_HOST || '127.0.0.1', |
|
|
port: parseInt(process.env.REDIS_PORT) || 6379, |
|
|
password: process.env.REDIS_PASSWORD || '', |
|
|
db: parseInt(process.env.REDIS_DB) || 0, |
|
|
connectTimeout: 10000, |
|
|
commandTimeout: 5000, |
|
|
retryDelayOnFailover: 100, |
|
|
maxRetriesPerRequest: 3, |
|
|
lazyConnect: true, |
|
|
enableTLS: process.env.REDIS_ENABLE_TLS === 'true' |
|
|
}, |
|
|
|
|
|
|
|
|
session: { |
|
|
|
|
|
stickyTtlHours: parseFloat(process.env.STICKY_SESSION_TTL_HOURS) || 1, |
|
|
|
|
|
renewalThresholdMinutes: parseInt(process.env.STICKY_SESSION_RENEWAL_THRESHOLD_MINUTES) || 0 |
|
|
}, |
|
|
|
|
|
|
|
|
claude: { |
|
|
apiUrl: process.env.CLAUDE_API_URL || 'https://api.anthropic.com/v1/messages', |
|
|
apiVersion: process.env.CLAUDE_API_VERSION || '2023-06-01', |
|
|
betaHeader: |
|
|
process.env.CLAUDE_BETA_HEADER || |
|
|
'claude-code-20250219,oauth-2025-04-20,interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14', |
|
|
overloadHandling: { |
|
|
enabled: (() => { |
|
|
const minutes = parseInt(process.env.CLAUDE_OVERLOAD_HANDLING_MINUTES) || 0 |
|
|
|
|
|
return Math.max(0, Math.min(minutes, 1440)) |
|
|
})() |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
bedrock: { |
|
|
enabled: process.env.CLAUDE_CODE_USE_BEDROCK === '1', |
|
|
defaultRegion: process.env.AWS_REGION || 'us-east-1', |
|
|
smallFastModelRegion: process.env.ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION, |
|
|
defaultModel: process.env.ANTHROPIC_MODEL || 'us.anthropic.claude-sonnet-4-20250514-v1:0', |
|
|
smallFastModel: |
|
|
process.env.ANTHROPIC_SMALL_FAST_MODEL || 'us.anthropic.claude-3-5-haiku-20241022-v1:0', |
|
|
maxOutputTokens: parseInt(process.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS) || 4096, |
|
|
maxThinkingTokens: parseInt(process.env.MAX_THINKING_TOKENS) || 1024, |
|
|
enablePromptCaching: process.env.DISABLE_PROMPT_CACHING !== '1' |
|
|
}, |
|
|
|
|
|
|
|
|
proxy: { |
|
|
timeout: parseInt(process.env.DEFAULT_PROXY_TIMEOUT) || 600000, |
|
|
maxRetries: parseInt(process.env.MAX_PROXY_RETRIES) || 3, |
|
|
|
|
|
useIPv4: process.env.PROXY_USE_IPV4 !== 'false' |
|
|
}, |
|
|
|
|
|
|
|
|
requestTimeout: parseInt(process.env.REQUEST_TIMEOUT) || 600000, |
|
|
|
|
|
|
|
|
limits: { |
|
|
defaultTokenLimit: parseInt(process.env.DEFAULT_TOKEN_LIMIT) || 1000000 |
|
|
}, |
|
|
|
|
|
|
|
|
logging: { |
|
|
level: process.env.LOG_LEVEL || 'info', |
|
|
dirname: path.join(__dirname, '..', 'logs'), |
|
|
maxSize: process.env.LOG_MAX_SIZE || '10m', |
|
|
maxFiles: parseInt(process.env.LOG_MAX_FILES) || 5 |
|
|
}, |
|
|
|
|
|
|
|
|
system: { |
|
|
cleanupInterval: parseInt(process.env.CLEANUP_INTERVAL) || 3600000, |
|
|
tokenUsageRetention: parseInt(process.env.TOKEN_USAGE_RETENTION) || 2592000000, |
|
|
healthCheckInterval: parseInt(process.env.HEALTH_CHECK_INTERVAL) || 60000, |
|
|
timezone: process.env.SYSTEM_TIMEZONE || 'Asia/Shanghai', |
|
|
timezoneOffset: parseInt(process.env.TIMEZONE_OFFSET) || 8 |
|
|
}, |
|
|
|
|
|
|
|
|
web: { |
|
|
title: process.env.WEB_TITLE || 'Claude Relay Service', |
|
|
description: |
|
|
process.env.WEB_DESCRIPTION || |
|
|
'Multi-account Claude API relay service with beautiful management interface', |
|
|
logoUrl: process.env.WEB_LOGO_URL || '/assets/logo.png', |
|
|
enableCors: process.env.ENABLE_CORS === 'true', |
|
|
sessionSecret: process.env.WEB_SESSION_SECRET || 'CHANGE-THIS-SESSION-SECRET' |
|
|
}, |
|
|
|
|
|
|
|
|
ldap: { |
|
|
enabled: process.env.LDAP_ENABLED === 'true', |
|
|
server: { |
|
|
url: process.env.LDAP_URL || 'ldap://localhost:389', |
|
|
bindDN: process.env.LDAP_BIND_DN || 'cn=admin,dc=example,dc=com', |
|
|
bindCredentials: process.env.LDAP_BIND_PASSWORD || 'admin', |
|
|
searchBase: process.env.LDAP_SEARCH_BASE || 'dc=example,dc=com', |
|
|
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'], |
|
|
timeout: parseInt(process.env.LDAP_TIMEOUT) || 5000, |
|
|
connectTimeout: parseInt(process.env.LDAP_CONNECT_TIMEOUT) || 10000, |
|
|
|
|
|
tls: { |
|
|
|
|
|
rejectUnauthorized: process.env.LDAP_TLS_REJECT_UNAUTHORIZED !== 'false', |
|
|
|
|
|
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, |
|
|
|
|
|
key: process.env.LDAP_TLS_KEY_FILE |
|
|
? require('fs').readFileSync(process.env.LDAP_TLS_KEY_FILE) |
|
|
: undefined, |
|
|
|
|
|
servername: process.env.LDAP_TLS_SERVERNAME || undefined |
|
|
} |
|
|
}, |
|
|
userMapping: { |
|
|
username: process.env.LDAP_USER_ATTR_USERNAME || 'uid', |
|
|
displayName: process.env.LDAP_USER_ATTR_DISPLAY_NAME || 'cn', |
|
|
email: process.env.LDAP_USER_ATTR_EMAIL || 'mail', |
|
|
firstName: process.env.LDAP_USER_ATTR_FIRST_NAME || 'givenName', |
|
|
lastName: process.env.LDAP_USER_ATTR_LAST_NAME || 'sn' |
|
|
} |
|
|
}, |
|
|
|
|
|
|
|
|
userManagement: { |
|
|
enabled: process.env.USER_MANAGEMENT_ENABLED === 'true', |
|
|
defaultUserRole: process.env.DEFAULT_USER_ROLE || 'user', |
|
|
userSessionTimeout: parseInt(process.env.USER_SESSION_TIMEOUT) || 86400000, |
|
|
maxApiKeysPerUser: parseInt(process.env.MAX_API_KEYS_PER_USER) || 1, |
|
|
allowUserDeleteApiKeys: process.env.ALLOW_USER_DELETE_API_KEYS === 'true' |
|
|
}, |
|
|
|
|
|
|
|
|
webhook: { |
|
|
enabled: process.env.WEBHOOK_ENABLED !== 'false', |
|
|
urls: process.env.WEBHOOK_URLS |
|
|
? process.env.WEBHOOK_URLS.split(',').map((url) => url.trim()) |
|
|
: [], |
|
|
timeout: parseInt(process.env.WEBHOOK_TIMEOUT) || 10000, |
|
|
retries: parseInt(process.env.WEBHOOK_RETRIES) || 3 |
|
|
}, |
|
|
|
|
|
|
|
|
development: { |
|
|
debug: process.env.DEBUG === 'true', |
|
|
hotReload: process.env.HOT_RELOAD === 'true' |
|
|
} |
|
|
} |
|
|
|
|
|
module.exports = config |
|
|
|