From 25f89a12b780c307c21014a6e66eb7bfb81a6136 Mon Sep 17 00:00:00 2001 From: 1e0n Date: Wed, 8 Oct 2025 19:42:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=8F=8C=E6=8E=88=E6=9D=83?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=EF=BC=9A=E6=94=AF=E6=8C=81FACTORY=5FAPI=5FKE?= =?UTF-8?q?Y=E7=8E=AF=E5=A2=83=E5=8F=98=E9=87=8F=E4=BC=98=E5=85=88?= =?UTF-8?q?=E7=BA=A7=E5=92=8C=E5=AE=A2=E6=88=B7=E7=AB=AF=E6=8E=88=E6=9D=83?= =?UTF-8?q?=E5=9B=9E=E9=80=80=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增FACTORY_API_KEY环境变量支持(最高优先级) - 保留现有refresh token自动刷新机制 - 添加客户端authorization头作为fallback - 优化启动流程,无认证配置时不报错退出 - 更新所有端点支持新的授权优先级系统 - 修改GPT-5-Codex推理级别为off --- auth.js | 111 +++++++++++++++++++++++++++++++--------------------- config.json | 2 +- routes.js | 6 +-- server.js | 3 +- 4 files changed, 72 insertions(+), 50 deletions(-) diff --git a/auth.js b/auth.js index cc4955f..57a30a7 100644 --- a/auth.js +++ b/auth.js @@ -9,8 +9,9 @@ let currentApiKey = null; let currentRefreshToken = null; let lastRefreshTime = null; let clientId = null; -let authSource = null; // 'env' or 'file' +let authSource = null; // 'env' or 'file' or 'factory_key' or 'client' let authFilePath = null; +let factoryApiKey = null; // From FACTORY_API_KEY environment variable const REFRESH_URL = 'https://api.workos.com/user_management/authenticate'; const REFRESH_INTERVAL_HOURS = 6; // Refresh every 6 hours @@ -57,19 +58,29 @@ function generateClientId() { } /** - * Load initial refresh token from environment or config file + * Load auth configuration with priority system + * Priority: FACTORY_API_KEY > refresh token mechanism > client authorization */ -function loadRefreshToken() { - // 1. Check environment variable DROID_REFRESH_KEY +function loadAuthConfig() { + // 1. Check FACTORY_API_KEY environment variable (highest priority) + const factoryKey = process.env.FACTORY_API_KEY; + if (factoryKey && factoryKey.trim() !== '') { + logInfo('Using fixed API key from FACTORY_API_KEY environment variable'); + factoryApiKey = factoryKey.trim(); + authSource = 'factory_key'; + return { type: 'factory_key', value: factoryKey.trim() }; + } + + // 2. Check refresh token mechanism (DROID_REFRESH_KEY) const envRefreshKey = process.env.DROID_REFRESH_KEY; if (envRefreshKey && envRefreshKey.trim() !== '') { logInfo('Using refresh token from DROID_REFRESH_KEY environment variable'); authSource = 'env'; authFilePath = path.join(process.cwd(), 'auth.json'); - return envRefreshKey.trim(); + return { type: 'refresh', value: envRefreshKey.trim() }; } - // 2. Check ~/.factory/auth.json + // 3. Check ~/.factory/auth.json const homeDir = os.homedir(); const factoryAuthPath = path.join(homeDir, '.factory', 'auth.json'); @@ -88,37 +99,17 @@ function loadRefreshToken() { currentApiKey = authData.access_token.trim(); } - return authData.refresh_token.trim(); + return { type: 'refresh', value: authData.refresh_token.trim() }; } } } catch (error) { logError('Error reading ~/.factory/auth.json', error); } - // 3. No refresh token found - throw error - const errorMessage = ` -╔════════════════════════════════════════════════════════════════╗ -║ Refresh Token Not Found ║ -╚════════════════════════════════════════════════════════════════╝ - -No valid refresh token found. Please use one of the following methods: - -1. Set environment variable: - export DROID_REFRESH_KEY="your_refresh_token_here" - -2. Or ensure ~/.factory/auth.json exists with valid refresh_token: - { - "access_token": "your_access_token", - "refresh_token": "your_refresh_token" - } - -Current status: - - DROID_REFRESH_KEY: ${envRefreshKey ? 'empty or whitespace' : 'not set'} - - ~/.factory/auth.json: ${fs.existsSync(factoryAuthPath) ? 'exists but invalid/empty refresh_token' : 'not found'} -`; - - logError(errorMessage); - throw new Error('Refresh token not found. Please configure DROID_REFRESH_KEY or ~/.factory/auth.json'); + // 4. No configured auth found - will use client authorization + logInfo('No auth configuration found, will use client authorization headers'); + authSource = 'client'; + return { type: 'client', value: null }; } /** @@ -235,14 +226,26 @@ function shouldRefresh() { } /** - * Initialize auth system - load refresh token and get initial API key + * Initialize auth system - load auth config and setup initial API key if needed */ export async function initializeAuth() { try { - currentRefreshToken = loadRefreshToken(); + const authConfig = loadAuthConfig(); - // Always refresh on startup to get fresh token - await refreshApiKey(); + if (authConfig.type === 'factory_key') { + // Using fixed FACTORY_API_KEY, no refresh needed + logInfo('Auth system initialized with fixed API key'); + } else if (authConfig.type === 'refresh') { + // Using refresh token mechanism + currentRefreshToken = authConfig.value; + + // Always refresh on startup to get fresh token + await refreshApiKey(); + logInfo('Auth system initialized with refresh token mechanism'); + } else { + // Using client authorization, no setup needed + logInfo('Auth system initialized for client authorization mode'); + } logInfo('Auth system initialized successfully'); } catch (error) { @@ -252,18 +255,36 @@ export async function initializeAuth() { } /** - * Get API key, refresh if needed + * Get API key based on configured authorization method + * @param {string} clientAuthorization - Authorization header from client request (optional) */ -export async function getApiKey() { - // Check if we need to refresh - if (shouldRefresh()) { - logInfo('API key needs refresh (6+ hours old)'); - await refreshApiKey(); +export async function getApiKey(clientAuthorization = null) { + // Priority 1: FACTORY_API_KEY environment variable + if (authSource === 'factory_key' && factoryApiKey) { + return `Bearer ${factoryApiKey}`; } + + // Priority 2: Refresh token mechanism + if (authSource === 'env' || authSource === 'file') { + // Check if we need to refresh + if (shouldRefresh()) { + logInfo('API key needs refresh (6+ hours old)'); + await refreshApiKey(); + } - if (!currentApiKey) { - throw new Error('No API key available. Please initialize auth system first.'); + if (!currentApiKey) { + throw new Error('No API key available from refresh token mechanism.'); + } + + return `Bearer ${currentApiKey}`; } - - return `Bearer ${currentApiKey}`; + + // Priority 3: Client authorization header + if (clientAuthorization) { + logDebug('Using client authorization header'); + return clientAuthorization; + } + + // No authorization available + throw new Error('No authorization available. Please configure FACTORY_API_KEY, refresh token, or provide client authorization.'); } diff --git a/config.json b/config.json index d926512..f564fa1 100644 --- a/config.json +++ b/config.json @@ -43,7 +43,7 @@ "name": "GPT-5-Codex", "id": "gpt-5-codex", "type": "openai", - "reasoning": "high" + "reasoning": "off" }, { "name": "GLM-4.6", diff --git a/routes.js b/routes.js index 7171e0d..4c1f1a2 100644 --- a/routes.js +++ b/routes.js @@ -66,7 +66,7 @@ async function handleChatCompletions(req, res) { // Get API key (will auto-refresh if needed) let authHeader; try { - authHeader = await getApiKey(); + authHeader = await getApiKey(req.headers.authorization); } catch (error) { logError('Failed to get API key', error); return res.status(500).json({ @@ -209,7 +209,7 @@ async function handleDirectResponses(req, res) { // Get API key let authHeader; try { - authHeader = await getApiKey(); + authHeader = await getApiKey(req.headers.authorization); } catch (error) { logError('Failed to get API key', error); return res.status(500).json({ @@ -338,7 +338,7 @@ async function handleDirectMessages(req, res) { // Get API key let authHeader; try { - authHeader = await getApiKey(); + authHeader = await getApiKey(req.headers.authorization); } catch (error) { logError('Failed to get API key', error); return res.status(500).json({ diff --git a/server.js b/server.js index 5d9a89a..9db93d6 100644 --- a/server.js +++ b/server.js @@ -110,7 +110,8 @@ app.use((err, req, res, next) => { logInfo('Configuration loaded successfully'); logInfo(`Dev mode: ${isDevMode()}`); - // Initialize auth system (load and refresh API key) + // Initialize auth system (load and setup API key if needed) + // This won't throw error if no auth config is found - will use client auth await initializeAuth(); const PORT = getPort();