Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,104 @@

This is an AI API gateway/proxy built with Go. It aggregates 40+ upstream AI providers (OpenAI, Claude, Gemini, Azure, AWS Bedrock, etc.) behind a unified API, with user management, billing, rate limiting, and an admin dashboard.

## Common Development Commands

### Backend (Go)

```bash
# Run backend development server
go run main.go

# Run with debug mode
GIN_MODE=debug DEBUG=true go run main.go

# Run with custom port
PORT=8080 go run main.go

# Run tests
go test ./...

# Run specific test
go test ./relay/channel -v -run TestClaude

# Run specific test file
go test ./relay/channel/api_request_test.go -v
```
Comment on lines +27 to +29

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix invalid go test invocation for a single file.

Line 28 uses a file path as the package argument, which is not a valid go test package pattern. Use a package target plus -run filter instead.

🧪 Proposed fix
-# Run specific test file
-go test ./relay/channel/api_request_test.go -v
+# Run tests in specific package (optionally add -run <TestName>)
+go test ./relay/channel -v
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Run specific test file
go test ./relay/channel/api_request_test.go -v
```
# Run tests in specific package (optionally add -run <TestName>)
go test ./relay/channel -v
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@CLAUDE.md` around lines 27 - 29, The README contains an invalid go test
invocation using a file path ("go test ./relay/channel/api_request_test.go -v");
replace it with a package-level invocation and an optional test filter — e.g.,
run the package (./relay/channel) and add -run with the test name or regex (or
use ./... for recursion) so use "go test ./relay/channel -v -run <TestName>"
instead of specifying the individual test file; update the CLAUDE.md entry to
show the corrected command.


### Frontend (React + Vite)

```bash
# Install dependencies (uses Bun)
cd web && bun install

# Run development server (runs on http://localhost:5173)
cd web && bun run dev

# Build for production
cd web && bun run build

# Run ESLint
cd web && bun run eslint

# Fix ESLint issues
cd web && bun run eslint:fix

# Format code with Prettier
cd web && bun run lint:fix

# i18n tools
cd web && bun run i18n:extract # Extract new translation keys
cd web && bun run i18n:sync # Sync translations
cd web && bun run i18n:lint # Lint translation files
```

### Full Stack Development

```bash
# Using makefile
make build-frontend # Build frontend assets
make start-backend # Start backend server
make all # Build frontend + start backend (parallel)

# Manually (two terminals)
# Terminal 1: Frontend dev server
cd web && bun run dev

# Terminal 2: Backend dev server
go run main.go
```

### Docker Development

```bash
# Start full stack with docker-compose
docker-compose up -d

# View logs
docker-compose logs -f

# Stop services
docker-compose down
```

### Environment Configuration

Create a `.env` file based on `.env.example`:

```bash
cp .env.example .env
# Then edit .env with your settings
```

Key environment variables:
- `SQL_DSN` - Database connection string (default: SQLite in `/data`)
- `REDIS_CONN_STRING` - Redis connection for cache
- `SESSION_SECRET` - Required for multi-machine deployments
- `CRYPTO_SECRET` - Required when using Redis
- `STREAMING_TIMEOUT` - Streaming timeout in seconds (default: 300)
- `DEBUG` - Enable debug mode
- `GIN_MODE` - Gin mode (`debug` or `release`)

## Tech Stack

- **Backend**: Go 1.22+, Gin web framework, GORM v2 ORM
Expand All @@ -24,6 +122,8 @@ service/ — Business logic
model/ — Data models and DB access (GORM)
relay/ — AI API relay/proxy with provider adapters
relay/channel/ — Provider-specific adapters (openai/, claude/, gemini/, aws/, etc.)
relay/common/ — Relay utilities and RelayInfo struct
relay/helper/ — Stream scanner, billing helpers, etc.
middleware/ — Auth, rate limiting, CORS, logging, distribution
setting/ — Configuration management (ratio, model, operation, system, performance)
common/ — Shared utilities (JSON, crypto, Redis, env, rate-limit, etc.)
Expand All @@ -37,6 +137,26 @@ web/ — React frontend
web/src/i18n/ — Frontend internationalization (i18next, zh/en/fr/ru/ja/vi)
```

### Relay System

The relay system is the core of the gateway, handling requests from clients and forwarding them to upstream AI providers:

- **Adaptor Interface** (`relay/channel/adapter.go`): All channel adapters implement this interface with methods like `Init`, `GetRequestURL`, `SetupRequestHeader`, `ConvertOpenAIRequest`, `DoRequest`, `DoResponse`, etc.
- **RelayInfo** (`relay/common/relay_info.go`): Contains all context for a single relay request - user/token info, channel metadata, pricing, billing session, request conversion chain.
- **Request Format Conversion**: Supports multiple relay formats - OpenAI, Claude Messages, Gemini, Responses, Rerank, Embedding, Audio, Image, Realtime, Task (async). Adapters convert between formats as needed.
- **Stream Handling**: `relay/helper/stream_scanner.go` handles streaming responses with configurable buffer size.
- **TaskAdaptor Interface**: For async task-based providers (Midjourney, Suno, etc.), implements polling-based task lifecycle management with billing hooks.

### Request Flow

1. Router receives request → Middleware (auth, rate limit, distribution)
2. Controller parses request → Validates token/channel
3. Service layer handles business logic (quota, billing)
4. Relay layer calls appropriate channel adaptor
5. Adaptor converts request format and forwards to upstream
6. Response is converted back and sent to client
7. Billing session settles quota (pre-consume -> adjust delta -> final settle)

## Internationalization (i18n)

### Backend (`i18n/`)
Expand Down
65 changes: 65 additions & 0 deletions docker-compose-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# new-api Docker Compose for Local Development
#
# Quick Start:
# docker-compose -f docker-compose-dev.yml up -d
#
# Purpose:
# This file contains only external services (database, cache) needed for development.
# The main new-api application runs on your local machine.
#
# Services:
# - postgres: PostgreSQL 17 database
# - redis: Redis cache server
# - redis-commander: Redis web UI (optional, for viewing cache)
# - pgadmin4: PostgreSQL web UI (optional, for database management)
#
version: '3.8'
name: new-api-dev

services:
postgres:
image: postgres:17-alpine
container_name: new-api-postgres-dev
restart: unless-stopped
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: 123456
POSTGRES_DB: new-api
Comment on lines +24 to +27

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid weak/default credentials in the shared dev compose file.

Line 26 uses a trivial DB password and Line 46 allows empty Redis password while binding public host ports. This is easy to misuse outside isolated local environments.

🔐 Proposed hardening for local defaults
     environment:
       POSTGRES_USER: root
-      POSTGRES_PASSWORD: 123456
+      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set in .env}
       POSTGRES_DB: new-api
       POSTGRES_INITDB_ARGS: "-E UTF8"
       TZ: Asia/Shanghai
@@
     environment:
-      - ALLOW_EMPTY_PASSWORD=yes
+      - ALLOW_EMPTY_PASSWORD=no
+      - REDIS_PASSWORD=${REDIS_PASSWORD:?set in .env}

Also applies to: 45-48

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docker-compose-dev.yml` around lines 24 - 27, The compose file currently sets
weak, hardcoded DB creds (POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB) and
leaves Redis unauthenticated while exposing public host ports; replace these
with secure defaults and reference external environment variables instead (e.g.
POSTGRES_PASSWORD, POSTGRES_USER, POSTGRES_DB loaded from a .env or CI secrets)
and avoid hardcoding "123456"; enable a REDIS_PASSWORD/requirepass and read it
from env rather than empty literal; and stop binding sensitive services to all
interfaces by removing public host port bindings or bind them to localhost
(127.0.0.1) for development to prevent accidental public exposure.

POSTGRES_INITDB_ARGS: "-E UTF8"
TZ: Asia/Shanghai
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U newapi"]
Comment on lines +25 to +35

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix PostgreSQL healthcheck credential mismatch.

Line 35 checks pg_isready -U newapi, but Line 25 sets POSTGRES_USER: root. This will keep the container unhealthy.

🐛 Proposed fix
     healthcheck:
-      test: ["CMD-SHELL", "pg_isready -U newapi"]
+      test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
       interval: 5s
       timeout: 5s
       retries: 5
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
POSTGRES_USER: root
POSTGRES_PASSWORD: 123456
POSTGRES_DB: new-api
POSTGRES_INITDB_ARGS: "-E UTF8"
TZ: Asia/Shanghai
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U newapi"]
POSTGRES_USER: root
POSTGRES_PASSWORD: 123456
POSTGRES_DB: new-api
POSTGRES_INITDB_ARGS: "-E UTF8"
TZ: Asia/Shanghai
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docker-compose-dev.yml` around lines 25 - 35, The healthcheck uses pg_isready
-U newapi but the container sets POSTGRES_USER: root, causing failed readiness
checks; update the healthcheck command (the test value that runs pg_isready -U
...) to use the actual POSTGRES_USER (root) or change POSTGRES_USER to match the
healthcheck (newapi) so they match; ensure the username passed to pg_isready and
the POSTGRES_USER/POSTGRES_DB values (POSTGRES_USER, POSTGRES_DB, and the
healthcheck test) are consistent.

interval: 5s
timeout: 5s
retries: 5

# Redis Cache Server
redis:
image: bitnamilegacy/redis:8.0
container_name: new-api-redis-dev
restart: unless-stopped
environment:
- ALLOW_EMPTY_PASSWORD=yes
ports:
- "6379:6379"
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5

volumes:
postgres_data:
driver: local
redis_data:
driver: local

networks:
default:
name: new-api-dev-network
140 changes: 140 additions & 0 deletions docs/learn_docs/01-项目概述.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# 项目概述

## 什么是 new-api

new-api 是一个基于 Go 语言的下一代大模型网关和 AI 资产管理系统。它将 40+ 个上游 AI 提供商(OpenAI、Claude、Gemini、Azure、AWS Bedrock 等)整合在一个统一的 API 接口下,提供用户管理、计费、限流和管理后台等功能。

## 核心功能

### 1. 多提供商聚合
```mermaid
graph TD
Client[客户端请求] --> Gateway[new-api 网关]
Gateway --> OpenAI[OpenAI]
Gateway --> Claude[Claude]
Gateway --> Gemini[Gemini]
Gateway --> Azure[Azure]
Gateway --> AWS[AWS Bedrock]
Gateway --> DeepSeek[DeepSeek]
Gateway --> Moonshot[Moonshot]
Gateway --> MiniMax[MiniMax]
Gateway --> Ali[通义千问]
Gateway --> Zhipu[智谱]
Gateway --> Others[其他30+提供商]
```

### 2. 多 API 格式支持
- **OpenAI 兼容格式** - `/v1/chat/completions`
- **OpenAI Responses 格式** - `/v1/responses`
- **Claude Messages 格式** - `/v1/messages`
- **Gemini 格式** - `/v1beta/models/...`
- **实时对话格式** - `/v1/realtime` (WebSocket)

### 3. 统一计费系统
支持多种计费模式:
- 按使用量计费(tokens)
- 按时间计费(音频/视频)
- 按图片数量计费
- 按分辨率/时长组合计费
- 任务预付费 + 完成结算

### 4. 智能路由策略
- **通道加权随机** - 按权重分配请求
- **自动重试** - 失败时自动切换通道
- **用户级模型限流** - 防止单用户占用过多资源
- **通道亲和性** - 会话级别的通道粘性

### 5. 异步任务系统
支持异步任务提供商:
- Midjourney - 图像生成
- Suno - 音乐生成
- Sora/Kling - 视频生成
- Jimeng - 即梦绘画

## 技术栈

| 层级 | 技术选型 |
|-------|----------|
| **后端框架** | Go 1.25.1, Gin Web Framework |
| **数据库** | SQLite, MySQL >= 5.7.8, PostgreSQL >= 9.6 |
| **缓存** | Redis (go-redis) + 内存缓存 |
| **ORM** | GORM v2 |
| **认证** | JWT, WebAuthn/Passkeys, OAuth (GitHub, Discord, OIDC) |
| **前端框架** | React 18, Vite |
| **UI 组件库** | Semi Design (@douyinfe/semi-ui) |
| **前端包管理器** | Bun |
| **国际化** | go-i18n (后端), i18next (前端) |

## 项目定位

### 目标用户
- 企业用户 - 需要 API 聚合和统一计费
- 开发者 - 需要简单接入多个 AI 模型
- 分发商 - 需要管理和计费终端用户

### 核心价值
1. **统一接入** - 一次接入 40+ AI 提供商
2. **成本可控** - 灵活的计费策略和限流
3. **高可用** - 自动重试和故障转移
4. **易管理** - 完整的用户、通道、日志管理后台

## 项目结构概览

```
new-api/
├── router/ # HTTP 路由层
├── controller/ # 请求处理层
├── service/ # 业务逻辑层
├── model/ # 数据模型和数据库访问
├── relay/ # AI API 转发核心
│ └── channel/ # 各提供商适配器
├── middleware/ # 中间件(认证、限流等)
├── setting/ # 配置管理
├── common/ # 通用工具
├── dto/ # 数据传输对象
├── constant/ # 常量定义
├── types/ # 类型定义
├── i18n/ # 后端国际化
├── oauth/ # OAuth 提供商实现
├── pkg/ # 内部包
└── web/ # React 前端
```

## 快速上手

### 1. 环境要求
- Go 1.25.1+
- Node.js 18+ (前端开发)
- Bun (前端包管理)
- SQLite/MySQL/PostgreSQL

### 2. 启动开发环境
```bash
# 后端
go run main.go

# 前端(在 web/ 目录)
cd web
bun install
bun run dev
```

### 3. 核心配置
```bash
# 数据库连接
SQL_DSN="user:password@tcp(localhost:3306)/newapi"

# Redis 连接(可选)
REDIS_CONN_STRING="redis://localhost:6379"

# 会话密钥(多机部署必填)
SESSION_SECRET="your-secret-key"

# 加密密钥(Redis 必填)
CRYPTO_SECRET="your-crypto-secret"
```

## 后续阅读

- [02-架构详解](./02-架构详解.md) - 深入了解系统架构
- [03-二次开发指南](./03-二次开发指南.md) - 学习如何扩展功能
Loading