7.4 KiB
AGENTS.md — Project Conventions for new-api
Overview
AI API gateway/proxy (Go) aggregating 40+ upstream AI providers behind a unified API, with user management, billing, rate limiting, and a React admin dashboard.
- Backend: Go 1.25+, Gin, GORM v2, testify
- Frontend: Two themes —
web/default/(React 19, Rsbuild, Base UI, Tailwind CSS 4, TanStack Router) andweb/classic/(React 18, Vite, Semi Design). Default is the primary. - Databases: SQLite, MySQL >= 5.7.8, PostgreSQL >= 9.6 (all three supported simultaneously)
- Cache: Redis (go-redis) + in-memory
- Auth: JWT, WebAuthn/Passkeys, OAuth (GitHub, Discord, OIDC)
- Desktop: Electron app at
electron/
Architecture
Layered: router/ → controller/ → service/ → model/
router/ — HTTP routing (api, relay, dashboard, web)
controller/ — Request handlers
service/ — Business logic
model/ — Data models and DB access (GORM), auto-migrations
relay/ — AI relay/proxy with 40+ provider adapters in relay/channel/
middleware/ — Auth, rate limiting, CORS, logging, distribution
setting/ — Config management (ratio, model, operation, system, performance)
common/ — Shared utilities (JSON, crypto, Redis, env, rate-limit, etc.)
dto/ — Request/response DTOs
constant/ — API types, channel types, context keys
types/ — Relay format types, file sources, errors
i18n/ — Backend i18n (go-i18n, 3 locales: en, zh-CN, zh-TW)
oauth/ — OAuth provider implementations
pkg/ — Internal packages: cachex, ionet, billingexpr, perf_metrics
web/ — Frontend themes: web/default/, web/classic/
Key Conventions
1. JSON — Use common/json.go wrappers
All marshal/unmarshal MUST use common.Marshal, common.Unmarshal, etc. Do NOT call encoding/json directly in business code. Type definitions from encoding/json (e.g. json.RawMessage) are still fine to reference.
2. Cross-DB Compatibility (SQLite, MySQL, PostgreSQL)
- Prefer GORM methods over raw SQL.
- Use
commonGroupCol,commonKeyCol,commonTrueVal,commonFalseValfrommodel/main.gofor reserved words and boolean literals. - Branch DB-specific logic with
common.UsingPostgreSQL,common.UsingSQLite,common.UsingMySQL. - Forbidden without cross-DB fallback: MySQL-only
GROUP_CONCAT, PostgreSQL@>/JSONBoperators,ALTER COLUMNon SQLite, DB-specific column types (useTEXTfor JSON). - Migrations must pass on all three DBs.
3. Frontend — Bun required
Use bun (not npm/yarn/pnpm) for web/default/:
bun install/bun run dev/bun run build- See
web/default/AGENTS.mdfor detailed frontend conventions (i18n, components, forms, routing, etc.)
4. New Channel — StreamOptions
When adding a channel, check if the provider supports StreamOptions. If so, add the channel type to streamSupportedChannels in relay/common/relay_info.go:320.
5. Protected Identity — DO NOT Modify
Do NOT remove, rename, or replace any reference to new-api (project) or QuantumNous (organization). This includes README, HTML titles, Go module paths, Docker images, package metadata, comments, and deployment configs.
6. Upstream DTOs — Pointer Types for Zero Values
Optional scalar fields in request structs that are parsed from client JSON and re-marshaled to upstream providers MUST use pointer types (*int, *float64, *bool, etc.) with omitempty. Non-nil pointer = preserve zero value. Non-pointer scalars with omitempty silently drop zeros.
7. Billing Expressions — Read pkg/billingexpr/expr.md
When working on tiered/dynamic billing, read pkg/billingexpr/expr.md first. It documents the expression language, system architecture, token normalization, and settlement rules.
Development
Run Backend
cp .env.example .env # edit as needed
go run main.go # starts on :3000
Build (matches CI/Docker)
The VERSION file is created by CI (from git tag). For a manual build:
echo "dev" > VERSION
(cd web/default && bun install && DISABLE_ESLINT_PLUGIN='true' bun run build)
go build -ldflags "-s -w -X 'github.com/QuantumNous/new-api/common.Version=$(cat VERSION)'" -o new-api
Run Backend Tests
go test ./... # all packages
go test ./pkg/billingexpr/... # single package
Run Frontend Dev
cd web/default && bun install && bun run dev
# proxies /api, /mj, /pg -> http://localhost:3000 (configurable via VITE_REACT_APP_SERVER_URL)
Other Scripts
cd web/default && bun run typecheck # tsc -b
cd web/default && bun run lint # eslint
cd web/default && bun run format # prettier --write
cd web/default && bun run i18n:sync # sync translation key structure
cd web/default && bun run knip # dead code detection
cd web/default && bun run build:check # typecheck + build
Frontend Dev Server Management
Background dev server (stays alive after tool invocation):
# Start (background, log to /tmp/frontend.log)
cd web/default && setsid bun run dev > /tmp/frontend.log 2>&1 &
# Stop
pkill -f "bun run dev"
# Restart
pkill -f "bun run dev" && cd web/default && setsid bun run dev > /tmp/frontend.log 2>&1 &
# Check status
ps aux | grep -E "rsbuild|bun" | grep -v grep
# View logs
tail -f /tmp/frontend.log
OpenAPI Specs
- Admin API:
docs/openapi/api.json(131 endpoints) - Relay API:
docs/openapi/relay.json(30+ endpoints)
CI/Docker
- Docker image:
calciumion/new-api. Multi-arch (amd64 + arm64). Multi-stage build: bun builds frontend, then Go builds the binary with embedded//go:embed web/default/dist. - PRs are checked by
peakoss/anti-slop(requires PR template, description, no AI-generated markers). - Tags trigger Docker pushes.
Local Dev + Production Deployment
Environment Layout
| Item | Dev (chaos user) | Prod (www user) |
|---|---|---|
| Directory | /home/chaos/new-api/ |
/home/www/new-api-prod/ |
| Port | localhost:3000 (API) / localhost:5173 (frontend hot-reload) |
localhost:3001 |
| Config | docker-compose.dev.yml |
/home/www/new-api-prod/docker-compose.prod.yml |
| Data | Docker volume dev_data |
/home/www/new-api-prod/data/ |
Git Remotes
origin→https://git.nomsg.cn/chaos/chaos-api.git(fork, push here)upstream→https://github.com/QuantumNous/new-api.git(official, pull from here)
Daily Workflow
# Sync upstream (auto-triggers deploy via post-merge hook)
git fetch upstream && git merge upstream/main
# Manual deploy
./deploy.sh
Deploy Script (deploy.sh)
Located at project root. Does three things:
- Builds frontend (
web/default/) with bun - Builds Docker image
my-new-api:latest - Restarts production containers as
wwwuser viasudo -u www docker compose ...
Git Hook
.git/hooks/post-merge automatically runs ./deploy.sh after git merge.
Permission Isolation
- chaos: owns code, builds images, triggers deploy via sudoers whitelist
- www: owns production data dir, runs production containers
- sudoers rule:
/etc/sudoers.d/chaos-deploy— chaos can only rundocker compose -f /home/www/new-api-prod/docker-compose.prod.yml *as www
Production Secrets
Stored in /home/www/new-api-prod/.env (owned by www, mode 600). Contains:
DB_PASS— PostgreSQL passwordREDIS_PASS— Redis passwordSESSION_SECRET— multi-node session secret