Browse Source

chore: sync VERSION file with release v0.1.32 [skip ci]

github-actions[bot] 4 months ago
parent
commit
bf5fcc5c1c
44 changed files with 180 additions and 182 deletions
  1. 1 1
      VERSION
  2. 5 5
      src/actions/active-sessions.ts
  3. 2 2
      src/actions/concurrent-sessions.ts
  4. 6 6
      src/actions/keys.ts
  5. 10 10
      src/actions/model-prices.ts
  6. 12 9
      src/actions/providers.ts
  7. 2 2
      src/actions/proxy-status.ts
  8. 2 2
      src/actions/statistics.ts
  9. 3 3
      src/actions/system-config.ts
  10. 4 4
      src/actions/usage-logs.ts
  11. 6 6
      src/actions/users.ts
  12. 2 2
      src/app/api/auth/login/route.ts
  13. 2 2
      src/app/api/leaderboard/route.ts
  14. 2 2
      src/app/api/proxy-status/route.ts
  15. 2 2
      src/app/api/version/route.ts
  16. 7 7
      src/app/settings/providers/_components/hooks/use-provider-edit.ts
  17. 2 2
      src/app/v1/[...route]/route.ts
  18. 26 31
      src/app/v1/_lib/codex/chat-completions-handler.ts
  19. 5 5
      src/app/v1/_lib/codex/codex-cli-adapter.ts
  20. 2 2
      src/app/v1/_lib/headers.ts
  21. 2 2
      src/app/v1/_lib/proxy-handler.ts
  22. 1 1
      src/app/v1/_lib/proxy/error-handler.ts
  23. 2 2
      src/app/v1/_lib/proxy/model-redirector.ts
  24. 1 1
      src/app/v1/_lib/proxy/rate-limit-guard.ts
  25. 10 10
      src/app/v1/_lib/proxy/response-handler.ts
  26. 5 5
      src/app/v1/_lib/proxy/session-guard.ts
  27. 1 1
      src/app/v1/_lib/proxy/session.ts
  28. 2 2
      src/app/v1/_lib/url.ts
  29. 4 4
      src/instrumentation.ts
  30. 1 1
      src/lib/config/env.schema.ts
  31. 9 9
      src/lib/migrate.ts
  32. 11 11
      src/lib/price-sync.ts
  33. 8 8
      src/lib/rate-limit/service.ts
  34. 8 8
      src/lib/redis/client.ts
  35. 2 2
      src/lib/redis/session-stats.ts
  36. 1 1
      src/lib/session-manager.ts
  37. 1 1
      src/lib/session-tracker.ts
  38. 2 2
      src/lib/utils/currency.ts
  39. 1 1
      src/middleware.ts
  40. 1 1
      src/repository/message.ts
  41. 1 1
      src/repository/provider.ts
  42. 1 1
      src/repository/system-config.ts
  43. 1 1
      src/repository/usage-logs.ts
  44. 1 1
      src/types/message.ts

+ 1 - 1
VERSION

@@ -1 +1 @@
-0.1.31
+0.1.32

+ 5 - 5
src/actions/active-sessions.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { SessionManager } from "@/lib/session-manager";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import type { ActionResult } from "./types";
 import type { ActiveSessionInfo } from "@/types/session";
 
@@ -17,7 +17,7 @@ export async function getActiveSessions(): Promise<ActionResult<ActiveSessionInf
       data: sessions,
     };
   } catch (error) {
-    logger.error('Failed to get active sessions:', error);
+    logger.error("Failed to get active sessions:", error);
     return {
       ok: false,
       error: "获取活跃 session 失败",
@@ -42,7 +42,7 @@ export async function getAllSessions(): Promise<
       data: sessions,
     };
   } catch (error) {
-    logger.error('Failed to get all sessions:', error);
+    logger.error("Failed to get all sessions:", error);
     return {
       ok: false,
       error: "获取 session 列表失败",
@@ -68,7 +68,7 @@ export async function getSessionMessages(sessionId: string): Promise<ActionResul
       data: messages,
     };
   } catch (error) {
-    logger.error('Failed to get session messages:', error);
+    logger.error("Failed to get session messages:", error);
     return {
       ok: false,
       error: "获取 session messages 失败",
@@ -88,7 +88,7 @@ export async function hasSessionMessages(sessionId: string): Promise<ActionResul
       data: messages !== null,
     };
   } catch (error) {
-    logger.error('Failed to check session messages:', error);
+    logger.error("Failed to check session messages:", error);
     return {
       ok: true,
       data: false, // 出错时默认返回 false,避免显示无效按钮

+ 2 - 2
src/actions/concurrent-sessions.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { getActiveConcurrentSessions } from "@/lib/redis";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import type { ActionResult } from "./types";
 
 /**
@@ -15,7 +15,7 @@ export async function getConcurrentSessions(): Promise<ActionResult<number>> {
       data: count,
     };
   } catch (error) {
-    logger.error('Failed to get concurrent sessions:', error);
+    logger.error("Failed to get concurrent sessions:", error);
     return {
       ok: false,
       error: "获取并发数失败",

+ 6 - 6
src/actions/keys.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { revalidatePath } from "next/cache";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { randomBytes } from "node:crypto";
 import { KeyFormSchema } from "@/lib/validation/schemas";
 import {
@@ -69,7 +69,7 @@ export async function addKey(data: {
     // 返回生成的key供前端显示
     return { ok: true, data: { generatedKey, name: validatedData.name } };
   } catch (error) {
-    logger.error('添加密钥失败:', error);
+    logger.error("添加密钥失败:", error);
     const message = error instanceof Error ? error.message : "添加密钥失败,请稍后重试";
     return { ok: false, error: message };
   }
@@ -110,7 +110,7 @@ export async function editKey(
     revalidatePath("/dashboard");
     return { ok: true };
   } catch (error) {
-    logger.error('更新密钥失败:', error);
+    logger.error("更新密钥失败:", error);
     const message = error instanceof Error ? error.message : "更新密钥失败,请稍后重试";
     return { ok: false, error: message };
   }
@@ -143,7 +143,7 @@ export async function removeKey(keyId: number): Promise<ActionResult> {
     revalidatePath("/dashboard");
     return { ok: true };
   } catch (error) {
-    logger.error('删除密钥失败:', error);
+    logger.error("删除密钥失败:", error);
     const message = error instanceof Error ? error.message : "删除密钥失败,请稍后重试";
     return { ok: false, error: message };
   }
@@ -165,7 +165,7 @@ export async function getKeys(userId: number): Promise<ActionResult<Key[]>> {
     const keys = await findKeyList(userId);
     return { ok: true, data: keys };
   } catch (error) {
-    logger.error('获取密钥列表失败:', error);
+    logger.error("获取密钥列表失败:", error);
     return { ok: false, error: "获取密钥列表失败" };
   }
 }
@@ -188,7 +188,7 @@ export async function getKeysWithStatistics(
     const stats = await findKeysWithStatistics(userId);
     return { ok: true, data: stats };
   } catch (error) {
-    logger.error('获取密钥统计失败:', error);
+    logger.error("获取密钥统计失败:", error);
     return { ok: false, error: "获取密钥统计失败" };
   }
 }

+ 10 - 10
src/actions/model-prices.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { revalidatePath } from "next/cache";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { getSession } from "@/lib/auth";
 import {
   findLatestPriceByModel,
@@ -97,7 +97,7 @@ export async function uploadPriceTable(
           result.unchanged.push(modelName);
         }
       } catch (error) {
-        logger.error('处理模型 ${modelName} 失败:', error);
+        logger.error("处理模型 ${modelName} 失败:", error);
         result.failed.push(modelName);
       }
     }
@@ -107,7 +107,7 @@ export async function uploadPriceTable(
 
     return { ok: true, data: result };
   } catch (error) {
-    logger.error('上传价格表失败:', error);
+    logger.error("上传价格表失败:", error);
     const message = error instanceof Error ? error.message : "上传失败,请稍后重试";
     return { ok: false, error: message };
   }
@@ -126,7 +126,7 @@ export async function getModelPrices(): Promise<ModelPrice[]> {
 
     return await findAllLatestPrices();
   } catch (error) {
-    logger.error('获取模型价格失败:', error);
+    logger.error("获取模型价格失败:", error);
     return [];
   }
 }
@@ -145,7 +145,7 @@ export async function hasPriceTable(): Promise<boolean> {
 
     return await hasAnyPriceRecords();
   } catch (error) {
-    logger.error('检查价格表失败:', error);
+    logger.error("检查价格表失败:", error);
     return false;
   }
 }
@@ -166,13 +166,13 @@ export async function syncLiteLLMPrices(): Promise<ActionResult<PriceUpdateResul
       return { ok: false, error: "无权限执行此操作" };
     }
 
-    logger.info('🔄 Starting LiteLLM price sync...');
+    logger.info("🔄 Starting LiteLLM price sync...");
 
     // 获取价格表 JSON(优先 CDN,降级缓存)
     const jsonContent = await getPriceTableJson();
 
     if (!jsonContent) {
-      logger.error('❌ Failed to get price table from both CDN and cache');
+      logger.error("❌ Failed to get price table from both CDN and cache");
       return {
         ok: false,
         error: "无法从 CDN 或缓存获取价格表,请检查网络连接或稍后重试",
@@ -183,14 +183,14 @@ export async function syncLiteLLMPrices(): Promise<ActionResult<PriceUpdateResul
     const result = await uploadPriceTable(jsonContent);
 
     if (result.ok) {
-      logger.info('✅ LiteLLM price sync completed', { result: result.data });
+      logger.info("✅ LiteLLM price sync completed", { result: result.data });
     } else {
-      logger.error('❌ LiteLLM price sync failed:', { context: result.error });
+      logger.error("❌ LiteLLM price sync failed:", { context: result.error });
     }
 
     return result;
   } catch (error) {
-    logger.error('❌ Sync LiteLLM prices failed:', error);
+    logger.error("❌ Sync LiteLLM prices failed:", error);
     const message = error instanceof Error ? error.message : "同步失败,请稍后重试";
     return { ok: false, error: message };
   }

+ 12 - 9
src/actions/providers.ts

@@ -8,7 +8,7 @@ import {
   getProviderStatistics,
 } from "@/repository/provider";
 import { revalidatePath } from "next/cache";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { type ProviderDisplay } from "@/types/provider";
 import { maskKey } from "@/lib/utils/validation";
 import { getSession } from "@/lib/auth";
@@ -23,7 +23,10 @@ export async function getProviders(): Promise<ProviderDisplay[]> {
     logger.trace("getProviders:session", { hasSession: !!session, role: session?.user.role });
 
     if (!session || session.user.role !== "admin") {
-      logger.trace("getProviders:unauthorized", { hasSession: !!session, role: session?.user.role });
+      logger.trace("getProviders:unauthorized", {
+        hasSession: !!session,
+        role: session?.user.role,
+      });
       return [];
     }
 
@@ -36,7 +39,7 @@ export async function getProviders(): Promise<ProviderDisplay[]> {
           stack: error.stack,
           name: error.name,
         });
-        logger.error('获取供应商统计数据失败:', error);
+        logger.error("获取供应商统计数据失败:", error);
         return []; // 统计查询失败时返回空数组,不影响供应商列表显示
       }),
     ]);
@@ -132,7 +135,7 @@ export async function getProviders(): Promise<ProviderDisplay[]> {
       message: error instanceof Error ? error.message : String(error),
       stack: error instanceof Error ? error.stack : undefined,
     });
-    logger.error('获取服务商数据失败:', error);
+    logger.error("获取服务商数据失败:", error);
     return [];
   }
 }
@@ -197,7 +200,7 @@ export async function addProvider(data: {
       message: error instanceof Error ? error.message : String(error),
       stack: error instanceof Error ? error.stack : undefined,
     });
-    logger.error('创建服务商失败:', error);
+    logger.error("创建服务商失败:", error);
     const message = error instanceof Error ? error.message : "创建服务商失败";
     return { ok: false, error: message };
   }
@@ -238,7 +241,7 @@ export async function editProvider(
     revalidatePath("/settings/providers");
     return { ok: true };
   } catch (error) {
-    logger.error('更新服务商失败:', error);
+    logger.error("更新服务商失败:", error);
     const message = error instanceof Error ? error.message : "更新服务商失败";
     return { ok: false, error: message };
   }
@@ -256,7 +259,7 @@ export async function removeProvider(providerId: number): Promise<ActionResult>
     revalidatePath("/settings/providers");
     return { ok: true };
   } catch (error) {
-    logger.error('删除服务商失败:', error);
+    logger.error("删除服务商失败:", error);
     const message = error instanceof Error ? error.message : "删除服务商失败";
     return { ok: false, error: message };
   }
@@ -301,7 +304,7 @@ export async function getProvidersHealthStatus() {
 
     return enrichedStatus;
   } catch (error) {
-    logger.error('获取熔断器状态失败:', error);
+    logger.error("获取熔断器状态失败:", error);
     return {};
   }
 }
@@ -321,7 +324,7 @@ export async function resetProviderCircuit(providerId: number): Promise<ActionRe
 
     return { ok: true };
   } catch (error) {
-    logger.error('重置熔断器失败:', error);
+    logger.error("重置熔断器失败:", error);
     const message = error instanceof Error ? error.message : "重置熔断器失败";
     return { ok: false, error: message };
   }

+ 2 - 2
src/actions/proxy-status.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { getSession } from "@/lib/auth";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { ProxyStatusTracker } from "@/lib/proxy-status-tracker";
 import type { ProxyStatusResponse } from "@/types/proxy-status";
 import type { ActionResult } from "./types";
@@ -17,7 +17,7 @@ export async function getProxyStatus(): Promise<ActionResult<ProxyStatusResponse
     const status = await tracker.getAllUsersStatus();
     return { ok: true, data: status };
   } catch (error) {
-    logger.error('获取代理状态失败:', error);
+    logger.error("获取代理状态失败:", error);
     return { ok: false, error: "获取代理状态失败" };
   }
 }

+ 2 - 2
src/actions/statistics.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { getSession } from "@/lib/auth";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import {
   getUserStatisticsFromDB,
   getActiveUsersFromDB,
@@ -149,7 +149,7 @@ export async function getUserStatistics(
       data: result,
     };
   } catch (error) {
-    logger.error('Failed to get user statistics:', error);
+    logger.error("Failed to get user statistics:", error);
 
     // 提供更具体的错误信息
     const errorMessage = error instanceof Error ? error.message : "未知错误";

+ 3 - 3
src/actions/system-config.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { revalidatePath } from "next/cache";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { getSystemSettings, updateSystemSettings } from "@/repository/system-config";
 import { getSession } from "@/lib/auth";
 import { UpdateSystemSettingsSchema } from "@/lib/validation/schemas";
@@ -18,7 +18,7 @@ export async function fetchSystemSettings(): Promise<ActionResult<SystemSettings
     const settings = await getSystemSettings();
     return { ok: true, data: settings };
   } catch (error) {
-    logger.error('获取系统设置失败:', error);
+    logger.error("获取系统设置失败:", error);
     return { ok: false, error: "获取系统设置失败" };
   }
 }
@@ -45,7 +45,7 @@ export async function saveSystemSettings(formData: {
 
     return { ok: true, data: updated };
   } catch (error) {
-    logger.error('更新系统设置失败:', error);
+    logger.error("更新系统设置失败:", error);
     const message = error instanceof Error ? error.message : "更新系统设置失败";
     return { ok: false, error: message };
   }

+ 4 - 4
src/actions/usage-logs.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { getSession } from "@/lib/auth";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import {
   findUsageLogsWithDetails,
   getUsedModels,
@@ -31,7 +31,7 @@ export async function getUsageLogs(
 
     return { ok: true, data: result };
   } catch (error) {
-    logger.error('获取使用日志失败:', error);
+    logger.error("获取使用日志失败:", error);
     const message = error instanceof Error ? error.message : "获取使用日志失败";
     return { ok: false, error: message };
   }
@@ -50,7 +50,7 @@ export async function getModelList(): Promise<ActionResult<string[]>> {
     const models = await getUsedModels();
     return { ok: true, data: models };
   } catch (error) {
-    logger.error('获取模型列表失败:', error);
+    logger.error("获取模型列表失败:", error);
     return { ok: false, error: "获取模型列表失败" };
   }
 }
@@ -68,7 +68,7 @@ export async function getStatusCodeList(): Promise<ActionResult<number[]>> {
     const codes = await getUsedStatusCodes();
     return { ok: true, data: codes };
   } catch (error) {
-    logger.error('获取状态码列表失败:', error);
+    logger.error("获取状态码列表失败:", error);
     return { ok: false, error: "获取状态码列表失败" };
   }
 }

+ 6 - 6
src/actions/users.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { findUserList, createUser, updateUser, deleteUser } from "@/repository/user";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { findKeyList, findKeyUsageToday, findKeysWithStatistics } from "@/repository/key";
 import { revalidatePath } from "next/cache";
 import { randomBytes } from "node:crypto";
@@ -87,7 +87,7 @@ export async function getUsers(): Promise<UserDisplay[]> {
             }),
           };
         } catch (error) {
-          logger.error('获取用户 ${user.id} 的密钥失败:', error);
+          logger.error("获取用户 ${user.id} 的密钥失败:", error);
           return {
             id: user.id,
             name: user.name,
@@ -104,7 +104,7 @@ export async function getUsers(): Promise<UserDisplay[]> {
 
     return userDisplays;
   } catch (error) {
-    logger.error('获取用户数据失败:', error);
+    logger.error("获取用户数据失败:", error);
     return [];
   }
 }
@@ -153,7 +153,7 @@ export async function addUser(data: {
     revalidatePath("/dashboard");
     return { ok: true };
   } catch (error) {
-    logger.error('添加用户失败:', error);
+    logger.error("添加用户失败:", error);
     const message = error instanceof Error ? error.message : "添加用户失败,请稍后重试";
     return { ok: false, error: message };
   }
@@ -189,7 +189,7 @@ export async function editUser(
     revalidatePath("/dashboard");
     return { ok: true };
   } catch (error) {
-    logger.error('更新用户失败:', error);
+    logger.error("更新用户失败:", error);
     const message = error instanceof Error ? error.message : "更新用户失败,请稍后重试";
     return { ok: false, error: message };
   }
@@ -207,7 +207,7 @@ export async function removeUser(userId: number): Promise<ActionResult> {
     revalidatePath("/dashboard");
     return { ok: true };
   } catch (error) {
-    logger.error('删除用户失败:', error);
+    logger.error("删除用户失败:", error);
     const message = error instanceof Error ? error.message : "删除用户失败,请稍后重试";
     return { ok: false, error: message };
   }

+ 2 - 2
src/app/api/auth/login/route.ts

@@ -1,5 +1,5 @@
 import { NextRequest, NextResponse } from "next/server";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { validateKey, setAuthCookie } from "@/lib/auth";
 
 export async function POST(request: NextRequest) {
@@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
       },
     });
   } catch (error) {
-    logger.error('Login error:', error);
+    logger.error("Login error:", error);
     return NextResponse.json({ error: "登录失败,请稍后重试" }, { status: 500 });
   }
 }

+ 2 - 2
src/app/api/leaderboard/route.ts

@@ -1,5 +1,5 @@
 import { NextRequest, NextResponse } from "next/server";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { findDailyLeaderboard, findMonthlyLeaderboard } from "@/repository/leaderboard";
 import { unstable_cache } from "next/cache";
 
@@ -54,7 +54,7 @@ export async function GET(request: NextRequest) {
       },
     });
   } catch (error) {
-    logger.error('获取排行榜失败:', error);
+    logger.error("获取排行榜失败:", error);
     return NextResponse.json({ error: "获取排行榜数据失败" }, { status: 500 });
   }
 }

+ 2 - 2
src/app/api/proxy-status/route.ts

@@ -1,5 +1,5 @@
 import { NextResponse } from "next/server";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { ProxyStatusTracker } from "@/lib/proxy-status-tracker";
 import { getSession } from "@/lib/auth";
 
@@ -36,7 +36,7 @@ export async function GET() {
 
     return NextResponse.json(status);
   } catch (error) {
-    logger.error('Failed to get proxy status:', error);
+    logger.error("Failed to get proxy status:", error);
     return NextResponse.json({ error: "获取代理状态失败" }, { status: 500 });
   }
 }

+ 2 - 2
src/app/api/version/route.ts

@@ -1,5 +1,5 @@
 import { NextResponse } from "next/server";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { APP_VERSION, GITHUB_REPO, compareVersions } from "@/lib/version";
 
 export const runtime = "edge";
@@ -58,7 +58,7 @@ export async function GET() {
       publishedAt: release.published_at,
     });
   } catch (error) {
-    logger.error('版本检查失败:', error);
+    logger.error("版本检查失败:", error);
     return NextResponse.json(
       {
         current: APP_VERSION,

+ 7 - 7
src/app/settings/providers/_components/hooks/use-provider-edit.ts

@@ -1,5 +1,5 @@
 import { useRef, useState } from "react";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { toast } from "sonner";
 import { editProvider } from "@/actions/providers";
 import type { ProviderDisplay } from "@/types/provider";
@@ -69,7 +69,7 @@ export function useProviderEdit(item: ProviderDisplay, canEdit: boolean) {
         throw new Error(res.error);
       }
     } catch (e) {
-      logger.error('切换服务商启用状态失败', { context: e });
+      logger.error("切换服务商启用状态失败", { context: e });
       setEnabled(prev);
       const msg = e instanceof Error ? e.message : "切换失败";
       toast.error(msg);
@@ -94,7 +94,7 @@ export function useProviderEdit(item: ProviderDisplay, canEdit: boolean) {
           if (!res.ok) throw new Error(res.error);
         })
         .catch((e) => {
-          logger.error('更新权重失败', { context: e });
+          logger.error("更新权重失败", { context: e });
           const msg = e instanceof Error ? e.message : "更新权重失败";
           toast.error(msg);
           setWeight(clampWeight(initialWeightRef.current));
@@ -120,7 +120,7 @@ export function useProviderEdit(item: ProviderDisplay, canEdit: boolean) {
           if (!res.ok) throw new Error(res.error);
         })
         .catch((e) => {
-          logger.error('更新5小时消费上限失败', { context: e });
+          logger.error("更新5小时消费上限失败", { context: e });
           const msg = e instanceof Error ? e.message : "更新5小时消费上限失败";
           toast.error(msg);
           setLimit5hInfinite(initial5hRef.current === null);
@@ -147,7 +147,7 @@ export function useProviderEdit(item: ProviderDisplay, canEdit: boolean) {
           if (!res.ok) throw new Error(res.error);
         })
         .catch((e) => {
-          logger.error('更新周消费上限失败', { context: e });
+          logger.error("更新周消费上限失败", { context: e });
           const msg = e instanceof Error ? e.message : "更新周消费上限失败";
           toast.error(msg);
           setLimitWeeklyInfinite(initialWeeklyRef.current === null);
@@ -174,7 +174,7 @@ export function useProviderEdit(item: ProviderDisplay, canEdit: boolean) {
           if (!res.ok) throw new Error(res.error);
         })
         .catch((e) => {
-          logger.error('更新月消费上限失败', { context: e });
+          logger.error("更新月消费上限失败", { context: e });
           const msg = e instanceof Error ? e.message : "更新月消费上限失败";
           toast.error(msg);
           setLimitMonthlyInfinite(initialMonthlyRef.current === null);
@@ -201,7 +201,7 @@ export function useProviderEdit(item: ProviderDisplay, canEdit: boolean) {
           if (!res.ok) throw new Error(res.error);
         })
         .catch((e) => {
-          logger.error('更新并发Session上限失败', { context: e });
+          logger.error("更新并发Session上限失败", { context: e });
           const msg = e instanceof Error ? e.message : "更新并发Session上限失败";
           toast.error(msg);
           setConcurrentInfinite(initialConcurrentRef.current === 0);

+ 2 - 2
src/app/v1/[...route]/route.ts

@@ -1,5 +1,5 @@
 import { Hono } from "hono";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { handle } from "hono/vercel";
 import { handleProxyRequest } from "@/app/v1/_lib/proxy-handler";
 import { handleChatCompletions } from "@/app/v1/_lib/codex/chat-completions-handler";
@@ -9,7 +9,7 @@ export const runtime = "nodejs";
 
 // 初始化 SessionTracker(清理旧 Set 格式数据)
 SessionTracker.initialize().catch((err) => {
-  logger.error('[App] SessionTracker initialization failed:', err);
+  logger.error("[App] SessionTracker initialization failed:", err);
 });
 
 const app = new Hono().basePath("/v1");

+ 26 - 31
src/app/v1/_lib/codex/chat-completions-handler.ts

@@ -1,5 +1,5 @@
 import type { Context } from "hono";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { ProxySession } from "../proxy/session";
 import { ProxyAuthenticator } from "../proxy/auth-guard";
 import { ProxyRateLimitGuard } from "../proxy/rate-limit-guard";
@@ -24,7 +24,7 @@ import type { ChatCompletionRequest } from "./types/compatible";
  * 5. 响应自动转换回 OpenAI 格式(在 ResponseHandler 中)
  */
 export async function handleChatCompletions(c: Context): Promise<Response> {
-  logger.info('[ChatCompletions] Received OpenAI Compatible API request');
+  logger.info("[ChatCompletions] Received OpenAI Compatible API request");
 
   const session = await ProxySession.fromContext(c);
 
@@ -66,7 +66,7 @@ export async function handleChatCompletions(c: Context): Promise<Response> {
         );
       }
 
-      logger.debug('[ChatCompletions] OpenAI format detected, transforming...', {
+      logger.debug("[ChatCompletions] OpenAI format detected, transforming...", {
         model: openAIRequest.model,
         stream: openAIRequest.stream,
         messageCount: openAIRequest.messages.length,
@@ -79,16 +79,15 @@ export async function handleChatCompletions(c: Context): Promise<Response> {
 
       // 开发模式:输出完整原始请求
       if (process.env.NODE_ENV === "development") {
-        logger.debug(
-          "[ChatCompletions] Full OpenAI request:",
-          { request: JSON.stringify(openAIRequest, null, 2) }
-        );
+        logger.debug("[ChatCompletions] Full OpenAI request:", {
+          request: JSON.stringify(openAIRequest, null, 2),
+        });
       }
 
       try {
         let responseRequest = RequestTransformer.transform(openAIRequest);
 
-        logger.debug('[ChatCompletions] Transformed to Response API:', {
+        logger.debug("[ChatCompletions] Transformed to Response API:", {
           model: responseRequest.model,
           inputCount: responseRequest.input?.length,
           hasReasoning: !!responseRequest.reasoning,
@@ -101,25 +100,22 @@ export async function handleChatCompletions(c: Context): Promise<Response> {
 
         // 开发模式:输出完整转换后请求
         if (process.env.NODE_ENV === "development") {
-          logger.debug(
-            "[ChatCompletions] Full Response API request:",
-            { request: JSON.stringify(responseRequest, null, 2) }
-          );
+          logger.debug("[ChatCompletions] Full Response API request:", {
+            request: JSON.stringify(responseRequest, null, 2),
+          });
         }
 
         // 适配 Codex CLI (注入 instructions)
         if (process.env.NODE_ENV === "development") {
-          logger.debug(
-            "[ChatCompletions] Before adaptForCodexCLI:",
-            { request: JSON.stringify(responseRequest, null, 2) }
-          );
+          logger.debug("[ChatCompletions] Before adaptForCodexCLI:", {
+            request: JSON.stringify(responseRequest, null, 2),
+          });
         }
         responseRequest = adaptForCodexCLI(responseRequest);
         if (process.env.NODE_ENV === "development") {
-          logger.debug(
-            "[ChatCompletions] After adaptForCodexCLI:",
-            { request: JSON.stringify(responseRequest, null, 2) }
-          );
+          logger.debug("[ChatCompletions] After adaptForCodexCLI:", {
+            request: JSON.stringify(responseRequest, null, 2),
+          });
         }
 
         // 更新 session(替换为 Response API 格式)
@@ -129,20 +125,19 @@ export async function handleChatCompletions(c: Context): Promise<Response> {
         // 验证转换结果(仅在开发环境)
         if (process.env.NODE_ENV === "development") {
           const msgObj = session.request.message as Record<string, unknown>;
-          logger.debug(
-            "[ChatCompletions] Verification - session.request.message contains input:",
-            {
-              hasInput: "input" in msgObj,
-              inputType: Array.isArray(msgObj.input) ? "array" : typeof msgObj.input,
-              inputLength: Array.isArray(msgObj.input) ? msgObj.input.length : "N/A",
-            }
-          );
+          logger.debug("[ChatCompletions] Verification - session.request.message contains input:", {
+            hasInput: "input" in msgObj,
+            inputType: Array.isArray(msgObj.input) ? "array" : typeof msgObj.input,
+            inputLength: Array.isArray(msgObj.input) ? msgObj.input.length : "N/A",
+          });
         }
 
         // 标记为 OpenAI 格式(用于响应转换)
         session.setOriginalFormat("openai");
       } catch (transformError) {
-        logger.error('[ChatCompletions] Request transformation failed:', { context: transformError });
+        logger.error("[ChatCompletions] Request transformation failed:", {
+          context: transformError,
+        });
         return new Response(
           JSON.stringify({
             error: {
@@ -156,7 +151,7 @@ export async function handleChatCompletions(c: Context): Promise<Response> {
       }
     } else if (isResponseAPIFormat) {
       // Response API 格式 → 直接透传
-      logger.info('[ChatCompletions] Response API format detected, passing through');
+      logger.info("[ChatCompletions] Response API format detected, passing through");
 
       // 标记为 Response API 格式(响应也用 Response API 格式)
       session.setOriginalFormat("response");
@@ -217,7 +212,7 @@ export async function handleChatCompletions(c: Context): Promise<Response> {
     // 5. 响应处理(自动转换回 OpenAI 格式)
     return await ProxyResponseHandler.dispatch(session, response);
   } catch (error) {
-    logger.error('[ChatCompletions] Handler error:', error);
+    logger.error("[ChatCompletions] Handler error:", error);
     return await ProxyErrorHandler.handle(session, error);
   }
 }

+ 5 - 5
src/app/v1/_lib/codex/codex-cli-adapter.ts

@@ -14,7 +14,7 @@
  */
 
 import type { ResponseRequest } from "./types/response";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { CODEX_CLI_INSTRUCTIONS, isCodexCLIRequest } from "./constants/codex-cli-instructions";
 
 /**
@@ -61,12 +61,12 @@ export function adaptForCodexCLI(request: ResponseRequest): ResponseRequest {
 
   // 步骤 1: 注入 instructions (如果开关启用)
   if (ENABLE_CODEX_CLI_INJECTION && !isCodexCLIRequest(request.instructions)) {
-    logger.info('[CodexCLI] Non-Codex CLI request detected, injecting instructions');
+    logger.info("[CodexCLI] Non-Codex CLI request detected, injecting instructions");
     adaptedRequest.instructions = CODEX_CLI_INSTRUCTIONS;
   } else if (ENABLE_CODEX_CLI_INJECTION) {
-    logger.info('[CodexCLI] Codex CLI request detected, skipping injection');
+    logger.info("[CodexCLI] Codex CLI request detected, skipping injection");
   } else {
-    logger.info('[CodexCLI] Injection disabled, skipping instructions');
+    logger.info("[CodexCLI] Injection disabled, skipping instructions");
   }
 
   // 步骤 2: 删除不兼容字段 (总是执行)
@@ -82,7 +82,7 @@ export function adaptForCodexCLI(request: ResponseRequest): ResponseRequest {
     logger.debug(`[CodexCLI] Removed incompatible fields: ${removedFields.join(", ")}`);
   }
 
-  logger.debug('[CodexCLI] Adapted request:', {
+  logger.debug("[CodexCLI] Adapted request:", {
     hasInstructions: !!adaptedRequest.instructions,
     instructionsLength: adaptedRequest.instructions?.length,
     removedFields,

+ 2 - 2
src/app/v1/_lib/headers.ts

@@ -1,4 +1,4 @@
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 
 /**
  * Header 处理器配置
@@ -78,7 +78,7 @@ export class HeaderProcessor {
       const url = new URL(baseUrl);
       return url.host;
     } catch (error) {
-      logger.error('提取 host 失败:', error);
+      logger.error("提取 host 失败:", error);
       const match = baseUrl.match(/^https?:\/\/([^\/]+)/);
       return match ? match[1] : "localhost";
     }

+ 2 - 2
src/app/v1/_lib/proxy-handler.ts

@@ -1,5 +1,5 @@
 import type { Context } from "hono";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { ProxySession } from "./proxy/session";
 import { ProxyAuthenticator } from "./proxy/auth-guard";
 import { ProxySessionGuard } from "./proxy/session-guard";
@@ -55,7 +55,7 @@ export async function handleProxyRequest(c: Context): Promise<Response> {
     const response = await ProxyForwarder.send(session);
     return await ProxyResponseHandler.dispatch(session, response);
   } catch (error) {
-    logger.error('Proxy handler error:', error);
+    logger.error("Proxy handler error:", error);
     return await ProxyErrorHandler.handle(session, error);
   }
 }

+ 1 - 1
src/app/v1/_lib/proxy/error-handler.ts

@@ -1,5 +1,5 @@
 import { updateMessageRequestDuration, updateMessageRequestDetails } from "@/repository/message";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { ProxyResponses } from "./responses";
 import { ProxyError } from "./errors";
 import type { ProxySession } from "./session";

+ 2 - 2
src/app/v1/_lib/proxy/model-redirector.ts

@@ -1,5 +1,5 @@
 import type { Provider } from "@/types/provider";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import type { ProxySession } from "./session";
 
 /**
@@ -25,7 +25,7 @@ export class ModelRedirector {
     // 获取原始模型名称
     const originalModel = session.request.model;
     if (!originalModel) {
-      logger.debug('[ModelRedirector] No model found in request, skipping redirect');
+      logger.debug("[ModelRedirector] No model found in request, skipping redirect");
       return false;
     }
 

+ 1 - 1
src/app/v1/_lib/proxy/rate-limit-guard.ts

@@ -1,5 +1,5 @@
 import type { ProxySession } from "./session";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { RateLimitService } from "@/lib/rate-limit";
 
 export class ProxyRateLimitGuard {

+ 10 - 10
src/app/v1/_lib/proxy/response-handler.ts

@@ -4,7 +4,7 @@ import {
   updateMessageRequestDetails,
 } from "@/repository/message";
 import { findLatestPriceByModel } from "@/repository/model-price";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { parseSSEData } from "@/lib/utils/sse";
 import { calculateRequestCost } from "@/lib/utils/cost-calculation";
 import { RateLimitService } from "@/lib/rate-limit";
@@ -61,7 +61,7 @@ export class ProxyResponseHandler {
         // 转换为 OpenAI 格式
         const openAIResponse = ResponseTransformer.transform(responseData);
 
-        logger.debug('[ResponseHandler] Transformed Response API → OpenAI format (non-stream)');
+        logger.debug("[ResponseHandler] Transformed Response API → OpenAI format (non-stream)");
 
         // 构建新的响应
         finalResponse = new Response(JSON.stringify(openAIResponse), {
@@ -70,7 +70,7 @@ export class ProxyResponseHandler {
           headers: new Headers(response.headers),
         });
       } catch (error) {
-        logger.error('[ResponseHandler] Failed to transform response:', error);
+        logger.error("[ResponseHandler] Failed to transform response:", error);
         // 转换失败时返回原始响应
         finalResponse = response;
       }
@@ -135,7 +135,7 @@ export class ProxyResponseHandler {
             status: statusCode >= 200 && statusCode < 300 ? "completed" : "error",
             statusCode: statusCode,
           }).catch((error: unknown) => {
-            logger.error('[ResponseHandler] Failed to update session usage:', error);
+            logger.error("[ResponseHandler] Failed to update session usage:", error);
           });
         }
 
@@ -164,7 +164,7 @@ export class ProxyResponseHandler {
           statusCode,
         });
       } catch (error) {
-        logger.error('Failed to handle non-stream log:', error);
+        logger.error("Failed to handle non-stream log:", error);
       }
     })();
 
@@ -184,7 +184,7 @@ export class ProxyResponseHandler {
     let processedStream: ReadableStream<Uint8Array> = response.body;
 
     if (needsTransform) {
-      logger.debug('[ResponseHandler] Transforming Response API → OpenAI format (stream)');
+      logger.debug("[ResponseHandler] Transforming Response API → OpenAI format (stream)");
 
       // 创建转换流
       const streamTransformer = new StreamTransformer();
@@ -231,7 +231,7 @@ export class ProxyResponseHandler {
               }
             }
           } catch (error) {
-            logger.error('[ResponseHandler] Stream transform error:', error);
+            logger.error("[ResponseHandler] Stream transform error:", error);
             // 出错时传递原始 chunk
             controller.enqueue(chunk);
           }
@@ -326,7 +326,7 @@ export class ProxyResponseHandler {
             status: statusCode >= 200 && statusCode < 300 ? "completed" : "error",
             statusCode: statusCode,
           }).catch((error: unknown) => {
-            logger.error('[ResponseHandler] Failed to update session usage:', error);
+            logger.error("[ResponseHandler] Failed to update session usage:", error);
           });
         }
 
@@ -340,7 +340,7 @@ export class ProxyResponseHandler {
           providerChain: session.getProviderChain(),
         });
       } catch (error) {
-        logger.error('Failed to save SSE content:', error);
+        logger.error("Failed to save SSE content:", error);
       } finally {
         reader.releaseLock();
       }
@@ -437,6 +437,6 @@ async function trackCostToRedis(session: ProxySession, usage: UsageMetrics | nul
 
   // 刷新 session 时间戳(滑动窗口)
   void SessionTracker.refreshSession(session.sessionId, key.id, provider.id).catch((error) => {
-    logger.error('[ResponseHandler] Failed to refresh session tracker:', error);
+    logger.error("[ResponseHandler] Failed to refresh session tracker:", error);
   });
 }

+ 5 - 5
src/app/v1/_lib/proxy/session-guard.ts

@@ -1,5 +1,5 @@
 import type { ProxySession } from "./session";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { SessionManager } from "@/lib/session-manager";
 import { SessionTracker } from "@/lib/session-tracker";
 
@@ -15,7 +15,7 @@ export class ProxySessionGuard {
   static async ensure(session: ProxySession): Promise<void> {
     const keyId = session.authState?.key?.id;
     if (!keyId) {
-      logger.warn('[ProxySessionGuard] No key ID, skipping session assignment');
+      logger.warn("[ProxySessionGuard] No key ID, skipping session assignment");
       return;
     }
 
@@ -34,7 +34,7 @@ export class ProxySessionGuard {
 
       // 5. 追踪 session(添加到活跃集合)
       void SessionTracker.trackSession(sessionId, keyId).catch((err) => {
-        logger.error('[ProxySessionGuard] Failed to track session:', err);
+        logger.error("[ProxySessionGuard] Failed to track session:", err);
       });
 
       // 6. 存储 session 详细信息到 Redis(用于实时监控)
@@ -57,7 +57,7 @@ export class ProxySessionGuard {
             }
           }
         } catch (error) {
-          logger.error('[ProxySessionGuard] Failed to store session info:', error);
+          logger.error("[ProxySessionGuard] Failed to store session info:", error);
         }
       })();
 
@@ -65,7 +65,7 @@ export class ProxySessionGuard {
         `[ProxySessionGuard] Session assigned: ${sessionId} (key=${keyId}, messagesLength=${session.getMessagesLength()}, clientProvided=${!!clientSessionId})`
       );
     } catch (error) {
-      logger.error('[ProxySessionGuard] Failed to assign session:', error);
+      logger.error("[ProxySessionGuard] Failed to assign session:", error);
       // 降级:生成新 session(不阻塞请求)
       const fallbackSessionId = SessionManager.generateSessionId();
       session.setSessionId(fallbackSessionId);

+ 1 - 1
src/app/v1/_lib/proxy/session.ts

@@ -1,5 +1,5 @@
 import type { Context } from "hono";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import type { Provider } from "@/types/provider";
 import type { User } from "@/types/user";
 import type { Key } from "@/types/key";

+ 2 - 2
src/app/v1/_lib/url.ts

@@ -1,4 +1,4 @@
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 
 /**
  * 构建代理目标URL
@@ -23,7 +23,7 @@ export function buildProxyUrl(baseUrl: string, requestUrl: URL): string {
 
     return baseUrlObj.toString();
   } catch (error) {
-    logger.error('URL构建失败:', error);
+    logger.error("URL构建失败:", error);
     // 降级到字符串拼接
     const normalizedBaseUrl = baseUrl.replace(/\/$/, "");
     return `${normalizedBaseUrl}${requestUrl.pathname}${requestUrl.search}`;

+ 4 - 4
src/instrumentation.ts

@@ -3,7 +3,7 @@
  * 在服务器启动时自动执行数据库迁移
  */
 
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 
 export async function register() {
   // 仅在服务器端执行
@@ -13,19 +13,19 @@ export async function register() {
     if (process.env.NODE_ENV === "production" && process.env.AUTO_MIGRATE !== "false") {
       const { checkDatabaseConnection, runMigrations } = await import("@/lib/migrate");
 
-      logger.info('Initializing Claude Code Hub');
+      logger.info("Initializing Claude Code Hub");
 
       // 等待数据库连接
       const isConnected = await checkDatabaseConnection();
       if (!isConnected) {
-        logger.error('Cannot start application without database connection');
+        logger.error("Cannot start application without database connection");
         process.exit(1);
       }
 
       // 执行迁移
       await runMigrations();
 
-      logger.info('Application ready');
+      logger.info("Application ready");
     }
   }
 }

+ 1 - 1
src/lib/config/env.schema.ts

@@ -1,5 +1,5 @@
 import { z } from "zod";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 
 /**
  * 环境变量验证schema

+ 9 - 9
src/lib/migrate.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { migrate } from "drizzle-orm/postgres-js/migrator";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { drizzle } from "drizzle-orm/postgres-js";
 import postgres from "postgres";
 import path from "path";
@@ -12,11 +12,11 @@ import path from "path";
  */
 export async function runMigrations() {
   if (!process.env.DSN) {
-    logger.error('❌ DSN environment variable is not set');
+    logger.error("❌ DSN environment variable is not set");
     process.exit(1);
   }
 
-  logger.info('🔄 Starting database migrations...');
+  logger.info("🔄 Starting database migrations...");
 
   const migrationClient = postgres(process.env.DSN, { max: 1 });
   const db = drizzle(migrationClient);
@@ -28,9 +28,9 @@ export async function runMigrations() {
     // 执行迁移
     await migrate(db, { migrationsFolder });
 
-    logger.info('Database migrations completed successfully!');
+    logger.info("Database migrations completed successfully!");
   } catch (error) {
-    logger.error('❌ Migration failed:', error);
+    logger.error("❌ Migration failed:", error);
     process.exit(1);
   } finally {
     // 关闭连接
@@ -43,7 +43,7 @@ export async function runMigrations() {
  */
 export async function checkDatabaseConnection(retries = 30, delay = 2000): Promise<boolean> {
   if (!process.env.DSN) {
-    logger.error('❌ DSN environment variable is not set');
+    logger.error("❌ DSN environment variable is not set");
     return false;
   }
 
@@ -52,16 +52,16 @@ export async function checkDatabaseConnection(retries = 30, delay = 2000): Promi
       const client = postgres(process.env.DSN, { max: 1 });
       await client`SELECT 1`;
       await client.end();
-      logger.info('Database connection established');
+      logger.info("Database connection established");
       return true;
     } catch (error) {
-      logger.error('⏳ Waiting for database... (${i + 1}/${retries})', error);
+      logger.error("⏳ Waiting for database... (${i + 1}/${retries})", error);
       if (i < retries - 1) {
         await new Promise((resolve) => setTimeout(resolve, delay));
       }
     }
   }
 
-  logger.error('Failed to connect to database after retries', { attempts: retries });
+  logger.error("Failed to connect to database after retries", { attempts: retries });
   return false;
 }

+ 11 - 11
src/lib/price-sync.ts

@@ -8,7 +8,7 @@
  */
 
 import fs from "fs/promises";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import path from "path";
 
 const LITELLM_PRICE_URL =
@@ -47,7 +47,7 @@ export async function fetchLiteLLMPrices(): Promise<string | null> {
     clearTimeout(timeoutId);
 
     if (!response.ok) {
-      logger.error('❌ Failed to fetch LiteLLM prices: HTTP ${response.status}');
+      logger.error("❌ Failed to fetch LiteLLM prices: HTTP ${response.status}");
       return null;
     }
 
@@ -56,14 +56,14 @@ export async function fetchLiteLLMPrices(): Promise<string | null> {
     // 验证 JSON 格式
     JSON.parse(jsonText);
 
-    logger.info('Successfully fetched LiteLLM prices from CDN');
+    logger.info("Successfully fetched LiteLLM prices from CDN");
     return jsonText;
   } catch (error) {
     if (error instanceof Error) {
       if (error.name === "AbortError") {
-        logger.error('❌ Fetch LiteLLM prices timeout after 10s');
+        logger.error("❌ Fetch LiteLLM prices timeout after 10s");
       } else {
-        logger.error('❌ Failed to fetch LiteLLM prices:', { context: error.message });
+        logger.error("❌ Failed to fetch LiteLLM prices:", { context: error.message });
       }
     }
     return null;
@@ -81,13 +81,13 @@ export async function readCachedPrices(): Promise<string | null> {
     // 验证 JSON 格式
     JSON.parse(cached);
 
-    logger.info('📦 Using cached LiteLLM prices');
+    logger.info("📦 Using cached LiteLLM prices");
     return cached;
   } catch (error) {
     if (error instanceof Error && "code" in error && error.code === "ENOENT") {
-      logger.info('ℹ️  No cached prices found');
+      logger.info("ℹ️  No cached prices found");
     } else {
-      logger.error('❌ Failed to read cached prices:', error);
+      logger.error("❌ Failed to read cached prices:", error);
     }
     return null;
   }
@@ -101,9 +101,9 @@ export async function saveCachedPrices(jsonText: string): Promise<void> {
   try {
     await ensureCacheDirectory();
     await fs.writeFile(CACHE_FILE_PATH, jsonText, "utf-8");
-    logger.info('💾 Saved prices to cache');
+    logger.info("💾 Saved prices to cache");
   } catch (error) {
-    logger.error('❌ Failed to save prices to cache:', error);
+    logger.error("❌ Failed to save prices to cache:", error);
   }
 }
 
@@ -122,6 +122,6 @@ export async function getPriceTableJson(): Promise<string | null> {
   }
 
   // 失败时降级使用缓存
-  logger.info('⚠️  CDN fetch failed, trying cache...');
+  logger.info("⚠️  CDN fetch failed, trying cache...");
   return await readCachedPrices();
 }

+ 8 - 8
src/lib/rate-limit/service.ts

@@ -1,5 +1,5 @@
 import { getRedisClient } from "@/lib/redis";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { SessionTracker } from "@/lib/session-tracker";
 import { CHECK_AND_TRACK_SESSION } from "@/lib/redis/lua-scripts";
 
@@ -52,7 +52,7 @@ export class RateLimitService {
 
         const [err, value] = results[index] || [];
         if (err) {
-          logger.error('[RateLimit] Redis error:', err);
+          logger.error("[RateLimit] Redis error:", err);
           return { allowed: true }; // Fail Open
         }
 
@@ -69,7 +69,7 @@ export class RateLimitService {
 
       return { allowed: true };
     } catch (error) {
-      logger.error('[RateLimit] Check failed:', error);
+      logger.error("[RateLimit] Check failed:", error);
       return { allowed: true }; // Fail Open
     }
   }
@@ -105,7 +105,7 @@ export class RateLimitService {
 
       return { allowed: true };
     } catch (error) {
-      logger.error('[RateLimit] Session check failed:', error);
+      logger.error("[RateLimit] Session check failed:", error);
       return { allowed: true }; // Fail Open
     }
   }
@@ -130,7 +130,7 @@ export class RateLimitService {
     }
 
     if (!this.redis || this.redis.status !== "ready") {
-      logger.warn('[RateLimit] Redis not ready, Fail Open');
+      logger.warn("[RateLimit] Redis not ready, Fail Open");
       return { allowed: true, count: 0, tracked: false };
     }
 
@@ -165,7 +165,7 @@ export class RateLimitService {
         tracked: true, // Lua 脚本中已追踪
       };
     } catch (error) {
-      logger.error('[RateLimit] Atomic check-and-track failed:', error);
+      logger.error("[RateLimit] Atomic check-and-track failed:", error);
       return { allowed: true, count: 0, tracked: false }; // Fail Open
     }
   }
@@ -206,7 +206,7 @@ export class RateLimitService {
 
       await pipeline.exec();
     } catch (error) {
-      logger.error('[RateLimit] Track cost failed:', error);
+      logger.error("[RateLimit] Track cost failed:", error);
       // 不抛出错误,静默失败
     }
   }
@@ -225,7 +225,7 @@ export class RateLimitService {
       const value = await this.redis.get(`${type}:${id}:cost_${period}`);
       return parseFloat(value || "0");
     } catch (error) {
-      logger.error('[RateLimit] Get cost failed:', error);
+      logger.error("[RateLimit] Get cost failed:", error);
       return 0;
     }
   }

+ 8 - 8
src/lib/redis/client.ts

@@ -1,5 +1,5 @@
 import Redis from "ioredis";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 
 let redisClient: Redis | null = null;
 
@@ -8,7 +8,7 @@ export function getRedisClient(): Redis | null {
   const isEnabled = process.env.ENABLE_RATE_LIMIT === "true";
 
   if (!isEnabled || !redisUrl) {
-    logger.warn('[Redis] Rate limiting disabled or REDIS_URL not configured');
+    logger.warn("[Redis] Rate limiting disabled or REDIS_URL not configured");
     return null;
   }
 
@@ -22,30 +22,30 @@ export function getRedisClient(): Redis | null {
       maxRetriesPerRequest: 3,
       retryStrategy(times) {
         if (times > 5) {
-          logger.error('[Redis] Max retries reached, giving up');
+          logger.error("[Redis] Max retries reached, giving up");
           return null; // 停止重试,降级
         }
         const delay = Math.min(times * 200, 2000);
-        logger.warn('[Redis] Retry ${times}/5 after ${delay}ms');
+        logger.warn("[Redis] Retry ${times}/5 after ${delay}ms");
         return delay;
       },
     });
 
     redisClient.on("connect", () => {
-      logger.info('[Redis] Connected successfully');
+      logger.info("[Redis] Connected successfully");
     });
 
     redisClient.on("error", (error) => {
-      logger.error('[Redis] Connection error:', error);
+      logger.error("[Redis] Connection error:", error);
     });
 
     redisClient.on("close", () => {
-      logger.warn('[Redis] Connection closed');
+      logger.warn("[Redis] Connection closed");
     });
 
     return redisClient;
   } catch (error) {
-    logger.error('[Redis] Failed to initialize:', error);
+    logger.error("[Redis] Failed to initialize:", error);
     return null;
   }
 }

+ 2 - 2
src/lib/redis/session-stats.ts

@@ -1,5 +1,5 @@
 import { SessionTracker } from "@/lib/session-tracker";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 
 /**
  * 获取当前活跃的并发 session 数量
@@ -16,7 +16,7 @@ export async function getActiveConcurrentSessions(): Promise<number> {
   try {
     return await SessionTracker.getGlobalSessionCount();
   } catch (error) {
-    logger.error('[SessionStats] Failed to get concurrent sessions:', error);
+    logger.error("[SessionStats] Failed to get concurrent sessions:", error);
     return 0; // Fail Open
   }
 }

+ 1 - 1
src/lib/session-manager.ts

@@ -1,5 +1,5 @@
 import crypto from "crypto";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { getRedisClient } from "./redis";
 import { SessionTracker } from "./session-tracker";
 import type {

+ 1 - 1
src/lib/session-tracker.ts

@@ -1,5 +1,5 @@
 import { getRedisClient } from "./redis";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 
 /**
  * Session 追踪器 - 统一管理活跃 Session 集合

+ 2 - 2
src/lib/utils/currency.ts

@@ -1,5 +1,5 @@
 import Decimal from "decimal.js-light";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import type { Numeric } from "decimal.js-light";
 
 Decimal.set({
@@ -29,7 +29,7 @@ export function toDecimal(value: DecimalInput): Decimal | null {
   try {
     return new Decimal(value);
   } catch (error) {
-    logger.error('Failed to create Decimal from value', { context: value, error });
+    logger.error("Failed to create Decimal from value", { context: value, error });
     return null;
   }
 }

+ 1 - 1
src/middleware.ts

@@ -11,7 +11,7 @@ export function middleware(request: NextRequest) {
   const pathname = request.nextUrl.pathname;
 
   if (isDevelopment()) {
-    logger.info('Request received', { method: method.toUpperCase(), pathname });
+    logger.info("Request received", { method: method.toUpperCase(), pathname });
   }
 
   // API 代理路由不需要 Web 鉴权(使用自己的 Bearer token)

+ 1 - 1
src/repository/message.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { db } from "@/drizzle/db";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { messageRequest } from "@/drizzle/schema";
 import { eq, isNull, and, desc, sql } from "drizzle-orm";
 import type { MessageRequest, CreateMessageRequestData } from "@/types/message";

+ 1 - 1
src/repository/provider.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { db } from "@/drizzle/db";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { providers } from "@/drizzle/schema";
 import { eq, isNull, and, desc, sql } from "drizzle-orm";
 import type { Provider, CreateProviderData, UpdateProviderData } from "@/types/provider";

+ 1 - 1
src/repository/system-config.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { db } from "@/drizzle/db";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { systemSettings } from "@/drizzle/schema";
 import { eq } from "drizzle-orm";
 import type { SystemSettings, UpdateSystemSettingsInput } from "@/types/system-config";

+ 1 - 1
src/repository/usage-logs.ts

@@ -1,7 +1,7 @@
 "use server";
 
 import { db } from "@/drizzle/db";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 import { messageRequest, users, keys as keysTable, providers } from "@/drizzle/schema";
 import { and, eq, isNull, gte, lte, desc, sql } from "drizzle-orm";
 import type { ProviderChainItem } from "@/types/message";

+ 1 - 1
src/types/message.ts

@@ -1,5 +1,5 @@
 import type { Numeric } from "decimal.js-light";
-import { logger } from '@/lib/logger';
+import { logger } from "@/lib/logger";
 
 /**
  * 供应商信息(用于决策链)