2026-03-03 20:10:53 -08:00
|
|
|
|
# CLAUDE.md
|
2025-07-14 18:14:13 +08:00
|
|
|
|
|
2026-03-03 20:10:53 -08:00
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
2025-07-14 18:14:13 +08:00
|
|
|
|
|
|
|
|
|
|
## 项目概述
|
|
|
|
|
|
|
2026-02-09 18:13:45 +08:00
|
|
|
|
Claude Relay Service — 多平台 AI API 中转服务,作为客户端与上游 AI API 之间的中间件。
|
|
|
|
|
|
支持 Claude (官方/Console)、Gemini、OpenAI Responses、AWS Bedrock、Azure OpenAI、Droid、CCR 等账户类型。
|
|
|
|
|
|
核心能力:多账户管理、API Key 认证、统一调度、代理配置、限流、成本统计。
|
2025-10-15 01:03:57 +08:00
|
|
|
|
|
2026-02-09 18:13:45 +08:00
|
|
|
|
## 架构原则
|
2025-10-15 01:03:57 +08:00
|
|
|
|
|
2026-02-09 18:13:45 +08:00
|
|
|
|
### Clean Architecture 分层映射
|
2025-07-14 18:14:13 +08:00
|
|
|
|
|
2026-02-09 18:13:45 +08:00
|
|
|
|
| 层级 | 目录 | 职责 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| **框架层** | `src/routes/`, `src/middleware/` | HTTP 路由、请求验证、响应格式化 |
|
|
|
|
|
|
| **接口适配层** | `src/handlers/`, `src/services/openaiToClaude.js` | 请求/响应格式转换 |
|
|
|
|
|
|
| **用例层** | `src/services/*Scheduler.js`, `*RelayService.js` | 调度逻辑、转发编排 |
|
|
|
|
|
|
| **实体层** | `src/services/*AccountService.js`, `src/models/` | 账户管理、数据模型 |
|
|
|
|
|
|
| **基础设施层** | `src/utils/`, `config/` | 日志、缓存、加密、代理 |
|
2025-07-14 18:14:13 +08:00
|
|
|
|
|
2026-02-09 18:13:45 +08:00
|
|
|
|
### 开发原则
|
2025-07-14 18:14:13 +08:00
|
|
|
|
|
2026-02-09 18:13:45 +08:00
|
|
|
|
- **依赖方向**: 外层 → 内层,内层不知道外层存在
|
|
|
|
|
|
- **新增路由**: 只做参数提取和响应格式化,业务逻辑放 service
|
|
|
|
|
|
- **新增服务**: 先确定属于哪一层,遵循该层职责边界
|
|
|
|
|
|
- **格式转换**: 不同 API 格式的转换放 handlers 或专用转换服务
|
|
|
|
|
|
- **数据访问**: 通过 `src/models/redis.js` 统一访问
|
2025-07-14 18:14:13 +08:00
|
|
|
|
|
2026-02-09 18:13:45 +08:00
|
|
|
|
### 安全约束
|
2025-08-22 22:09:38 +08:00
|
|
|
|
|
2026-02-09 18:13:45 +08:00
|
|
|
|
- 敏感数据(OAuth token、refreshToken、credentials)必须 AES 加密存储(参考 `claudeAccountService.js`)
|
|
|
|
|
|
- API Key 使用 SHA-256 哈希存储,禁止明文
|
|
|
|
|
|
- 每个请求必须经过完整认证链(API Key → 权限 → 客户端限制 → 模型黑名单)
|
|
|
|
|
|
- 客户端断开时必须通过 AbortController 清理资源和并发计数
|
|
|
|
|
|
- 日志中禁止输出完整 token,使用 `tokenMask.js` 脱敏
|
|
|
|
|
|
|
|
|
|
|
|
## 项目结构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
src/
|
|
|
|
|
|
├── routes/ # HTTP 路由
|
|
|
|
|
|
│ ├── api.js # Claude API 主路由
|
|
|
|
|
|
│ ├── admin/ # 管理后台路由(24个子文件)
|
|
|
|
|
|
│ ├── geminiRoutes.js, standardGeminiRoutes.js
|
|
|
|
|
|
│ ├── openaiRoutes.js, openaiClaudeRoutes.js, openaiGeminiRoutes.js
|
|
|
|
|
|
│ ├── azureOpenaiRoutes.js, droidRoutes.js
|
|
|
|
|
|
│ ├── userRoutes.js, webhook.js, unified.js, apiStats.js, web.js
|
|
|
|
|
|
├── middleware/ # auth.js(认证/权限/限流), browserFallback.js
|
|
|
|
|
|
├── handlers/ # geminiHandlers.js
|
|
|
|
|
|
├── services/ # 业务服务
|
|
|
|
|
|
│ ├── relay/ # 各平台转发服务(9个)
|
|
|
|
|
|
│ ├── account/ # 各平台账户管理(11个)
|
|
|
|
|
|
│ ├── scheduler/ # 统一调度器(4个)
|
|
|
|
|
|
│ ├── apiKeyService.js # API Key 管理
|
|
|
|
|
|
│ ├── pricingService.js # 定价和成本
|
|
|
|
|
|
│ └── ... # 其余 ~30 个业务服务
|
|
|
|
|
|
├── models/redis.js # Redis 数据模型
|
|
|
|
|
|
├── utils/ # 35+ 工具文件(logger, proxy, oauth, cache, stream...)
|
|
|
|
|
|
config/config.js # 主配置
|
|
|
|
|
|
scripts/ # 运维脚本
|
|
|
|
|
|
cli/ # CLI 工具
|
|
|
|
|
|
web/admin-spa/ # Vue SPA 管理界面
|
|
|
|
|
|
data/init.json # 管理员凭据
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 核心请求流程
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
客户端(cr_前缀Key) → 路由 → auth中间件(验证/权限/限流/模型黑名单)
|
|
|
|
|
|
→ 统一调度器(选账户/粘性会话) → Token检查/刷新
|
|
|
|
|
|
→ 转发服务(通过代理发送) → 上游API
|
|
|
|
|
|
→ 流式/非流式响应 → Usage捕获 → 成本计算 → 返回客户端
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
关键机制:
|
|
|
|
|
|
- **粘性会话**: 基于请求内容 hash 绑定账户,同一会话用同一账户
|
|
|
|
|
|
- **并发控制**: Redis Sorted Set 实现,支持排队等待(非直接 429)
|
|
|
|
|
|
- **529 处理**: 自动标记过载账户,配置时长内排除
|
|
|
|
|
|
- **加密存储**: 敏感数据(OAuth token、credentials)AES 加密存于 Redis
|
|
|
|
|
|
- **流式响应**: SSE 传输,实时捕获 usage,客户端断开时 AbortController 清理资源
|
2025-08-22 22:09:38 +08:00
|
|
|
|
|
2026-02-09 18:13:45 +08:00
|
|
|
|
## 开发规范
|
2025-07-14 18:14:13 +08:00
|
|
|
|
|
2026-03-03 20:10:53 -08:00
|
|
|
|
### 代码风格
|
2025-08-22 22:09:38 +08:00
|
|
|
|
|
2026-03-03 20:10:53 -08:00
|
|
|
|
- **无分号**、**单引号**、**100字符行宽**、**尾逗号 none**、**箭头函数始终加括号**
|
|
|
|
|
|
- 强制 `const`(`no-var`、`prefer-const`),严格相等(`eqeqeq`)
|
|
|
|
|
|
- 下划线前缀变量 `_var` 可豁免 unused 检查
|
2026-02-09 18:13:45 +08:00
|
|
|
|
- **必须使用 Prettier**: `npx prettier --write <file>`
|
|
|
|
|
|
- 前端额外安装了 `prettier-plugin-tailwindcss`
|
2025-07-14 18:14:13 +08:00
|
|
|
|
|
2025-07-15 18:00:52 +08:00
|
|
|
|
### 开发工作流
|
2025-08-22 22:09:38 +08:00
|
|
|
|
|
2026-02-09 18:13:45 +08:00
|
|
|
|
1. **理解现有代码** → 读相关文件,了解现有模式
|
|
|
|
|
|
2. **编写代码** → 重用已有服务和工具函数
|
|
|
|
|
|
3. **格式化** → `npx prettier --write <修改的文件>`
|
|
|
|
|
|
4. **检查** → `npm run lint`
|
|
|
|
|
|
5. **测试** → `npm test`
|
|
|
|
|
|
6. **验证** → `npm run cli status` 确认服务正常
|
|
|
|
|
|
|
2026-03-03 20:10:53 -08:00
|
|
|
|
### 测试规范
|
|
|
|
|
|
|
|
|
|
|
|
- 测试文件在 `tests/` 目录,命名 `*.test.js` 或 `*.spec.js`
|
|
|
|
|
|
- 使用 `jest.mock()` 模拟依赖(logger、redis、services)
|
|
|
|
|
|
- `beforeEach` 中 `jest.resetModules()`,`afterEach` 中 `jest.clearAllMocks()`
|
|
|
|
|
|
|
2026-02-09 18:13:45 +08:00
|
|
|
|
### 前端要求
|
|
|
|
|
|
|
2026-03-03 20:10:53 -08:00
|
|
|
|
- 技术栈:Vue 3 Composition API + Pinia + Element Plus + Tailwind CSS
|
2026-02-09 18:13:45 +08:00
|
|
|
|
- 响应式设计:Tailwind CSS 响应式前缀(sm:、md:、lg:、xl:)
|
|
|
|
|
|
- 暗黑模式:所有组件必须兼容,使用 `dark:` 前缀
|
|
|
|
|
|
- 主题切换:`web/admin-spa/src/stores/theme.js` 的 `useThemeStore()`
|
|
|
|
|
|
- 保持现有玻璃态设计风格
|
|
|
|
|
|
|
|
|
|
|
|
暗黑模式配色对照:
|
|
|
|
|
|
|
|
|
|
|
|
| 元素 | 明亮模式 | 暗黑模式 |
|
|
|
|
|
|
|------|----------|----------|
|
|
|
|
|
|
| 文本 | `text-gray-700` | `dark:text-gray-200` |
|
|
|
|
|
|
| 背景 | `bg-white` | `dark:bg-gray-800` |
|
|
|
|
|
|
| 边框 | `border-gray-200` | `dark:border-gray-700` |
|
|
|
|
|
|
| 状态色 | `text-blue-500` / `text-green-600` / `text-red-500` | 保持一致 |
|
|
|
|
|
|
|
|
|
|
|
|
### 代码修改原则
|
|
|
|
|
|
|
|
|
|
|
|
- 先检查现有模式和风格,重用已有服务和工具函数
|
|
|
|
|
|
- 敏感数据必须加密存储(参考 claudeAccountService.js)
|
|
|
|
|
|
- 遵循现有的错误处理和日志记录模式
|
|
|
|
|
|
|
|
|
|
|
|
## 常用命令
|
2025-08-22 22:09:38 +08:00
|
|
|
|
|
2025-07-15 18:00:52 +08:00
|
|
|
|
```bash
|
2026-02-09 18:13:45 +08:00
|
|
|
|
npm install && npm run setup # 初始化
|
2026-03-03 20:10:53 -08:00
|
|
|
|
npm run dev # 开发模式(nodemon 热重载,自动 lint)
|
|
|
|
|
|
npm start # 生产模式(先 lint 再启动)
|
|
|
|
|
|
npm run lint # ESLint 检查并自动修复
|
|
|
|
|
|
npm run lint:check # ESLint 仅检查不修复
|
|
|
|
|
|
npm run format # Prettier 格式化所有后端文件
|
|
|
|
|
|
npm run format:check # Prettier 仅检查格式
|
|
|
|
|
|
npm test # Jest 运行所有测试(tests/ 目录)
|
|
|
|
|
|
npm test -- <文件名> # 运行单个测试,如: npm test -- pricingService
|
|
|
|
|
|
npm test -- --coverage # 运行测试并生成覆盖率报告
|
2026-02-09 18:13:45 +08:00
|
|
|
|
npm run cli status # 系统状态
|
|
|
|
|
|
npm run data:export # 导出 Redis 数据
|
|
|
|
|
|
npm run data:debug # 调试 Redis 键
|
2025-07-26 11:41:17 +08:00
|
|
|
|
```
|
2025-08-22 22:09:38 +08:00
|
|
|
|
|
2026-03-03 20:10:53 -08:00
|
|
|
|
### 前端命令
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
|
npm run install:web # 安装前端依赖
|
|
|
|
|
|
npm run build:web # 构建前端(生成 dist)
|
|
|
|
|
|
cd web/admin-spa && npm run dev # 前端开发模式(Vite HMR)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-09 18:13:45 +08:00
|
|
|
|
## 环境变量(必须)
|
|
|
|
|
|
|
|
|
|
|
|
- `JWT_SECRET` — JWT 密钥(32字符+)
|
|
|
|
|
|
- `ENCRYPTION_KEY` — AES 加密密钥(32字符固定)
|
|
|
|
|
|
- `REDIS_HOST` / `REDIS_PORT` / `REDIS_PASSWORD` — Redis 连接
|
|
|
|
|
|
|
|
|
|
|
|
其他可选环境变量见 `.env.example`。
|
|
|
|
|
|
|
|
|
|
|
|
## 故障排除
|
|
|
|
|
|
|
|
|
|
|
|
| 问题 | 排查方向 |
|
|
|
|
|
|
|------|----------|
|
|
|
|
|
|
| Redis 连接失败 | 检查 REDIS_HOST/PORT/PASSWORD |
|
|
|
|
|
|
| 管理员登录失败 | 检查 data/init.json,运行 `npm run setup` |
|
|
|
|
|
|
| API Key 格式错误 | 确保使用 `cr_` 前缀格式(可通过 API_KEY_PREFIX 配置) |
|
|
|
|
|
|
| Token 刷新失败 | 检查 refreshToken 有效性和代理配置,查看 `logs/token-refresh-error.log` |
|
|
|
|
|
|
| 调度器选账户失败 | 检查账户 status:'active',确认类型与路由匹配,查看粘性会话绑定 |
|
|
|
|
|
|
| 并发计数泄漏 | 系统每分钟自动清理,重启也会清理 |
|
|
|
|
|
|
| 粘性会话失效 | 检查 Redis 中 session 数据,Nginx 代理需添加 `underscores_in_headers on` |
|
|
|
|
|
|
| LDAP 认证失败 | 检查 LDAP_URL/BIND_DN/BIND_PASSWORD,自签名证书设 `LDAP_TLS_REJECT_UNAUTHORIZED=false` |
|
|
|
|
|
|
| Webhook 通知失败 | 确认 WEBHOOK_ENABLED=true,检查 WEBHOOK_URLS 格式,查看 `logs/webhook-*.log` |
|
|
|
|
|
|
| 成本统计不准确 | 运行 `npm run init:costs`,检查 pricingService 模型价格 |
|
|
|
|
|
|
|
|
|
|
|
|
日志:`logs/` 目录。Web 界面 `/admin-next/` 可实时查看。
|
|
|
|
|
|
|
2025-07-26 11:41:17 +08:00
|
|
|
|
# important-instruction-reminders
|
2025-08-22 22:09:38 +08:00
|
|
|
|
|
2025-07-26 11:41:17 +08:00
|
|
|
|
Do what has been asked; nothing more, nothing less.
|
|
|
|
|
|
NEVER create files unless they're absolutely necessary for achieving your goal.
|
|
|
|
|
|
ALWAYS prefer editing an existing file to creating a new one.
|
2025-08-22 22:09:38 +08:00
|
|
|
|
NEVER proactively create documentation files (\*.md) or README files. Only create documentation files if explicitly requested by the User.
|