From 06cbb25a546b1b97ddbc008dbc80c6a3172384aa Mon Sep 17 00:00:00 2001
From: Jay
| One compatible gateway | OpenAI-style Chat Completions / Responses / Images, Anthropic Messages, prefixless compatibility routes, and native Codex Responses forwarding are all exposed through one service. |
| Account-pool scheduler | Selection is driven by account status, health tier, scheduler score, dynamic concurrency, cooldown recovery, and recent usage so unhealthy accounts are avoided automatically. Supports round_robin and remaining_quota modes, with per-account credit billing flags. |
| Visual admin console | The embedded React / Vite dashboard covers account import and testing, API keys, proxy pools, image studio (text-to-image + image-to-image), prompt filtering, usage analytics, operations, scheduler board, and system settings. |
| Two deployment shapes | Use PostgreSQL + Redis for production or SQLite + Memory for lightweight single-node deployments; Docker images, source builds, local development, and the interactive deploy script are ready to use. SQLite mode binds to 127.0.0.1 by default for security. |
| Billing and observability | Per-account 5h/7d windowed USD cost tracking, credit quota support, API key usage tracking, OAuth PKCE token acquisition, prompt filtering, and a usage dashboard with request logs and trend charts. |
| Quality check | Compare selected accounts, models, and reasoning effort with an editable pelican-on-a-bicycle HTML/SVG animation challenge. Run up to three background tests across accounts, keep persistent test history, and review isolated animation previews, source, timing/token metrics, and HTML downloads. |
docker-compose.yml | Recommended for servers and test environments |
+| Local source build | docker-compose.local.yml | Build and verify the current source |
+| SQLite image | docker-compose.sqlite.yml | Single-node deployment without PostgreSQL or Redis |
+| SQLite source build | docker-compose.sqlite.local.yml | Verify the lightweight SQLite mode |
+| Local development | go run . + npm run dev | Backend and frontend development |
-### Commands
+### Standard deployment
-Standard image mode:
-
-```bash
-git clone https://github.com/james-6-23/codex2api.git
+~~~bash
+git clone --branch codex2api-custom https://github.com/JayHome137/codex2api.git
cd codex2api
cp .env.example .env
docker compose pull
docker compose up -d
docker compose logs -f codex2api
-```
+~~~
-Standard local build mode:
+### Local source build
-```bash
+~~~bash
cp .env.example .env
docker compose -f docker-compose.local.yml up -d --build
docker compose -f docker-compose.local.yml logs -f codex2api
-```
+~~~
-SQLite image mode:
+### SQLite deployment
-```bash
+~~~bash
cp .env.sqlite.example .env
docker compose -f docker-compose.sqlite.yml pull
docker compose -f docker-compose.sqlite.yml up -d
docker compose -f docker-compose.sqlite.yml logs -f codex2api
-```
+~~~
-SQLite local build mode:
-
-```bash
-cp .env.sqlite.example .env
-docker compose -f docker-compose.sqlite.local.yml up -d --build
-docker compose -f docker-compose.sqlite.local.yml logs -f codex2api
-```
+The SQLite compose files bind to 127.0.0.1 by default. Set BIND_HOST=0.0.0.0 when external access is required. The standard compose files bind to all interfaces by default.
After startup:
-- Admin dashboard: `http://localhost:8080/admin/`
-- Health check: `http://localhost:8080/health`
-
-Notes:
-
-- Standard and SQLite modes both read `.env`.
-- Before switching deployment modes, replace `.env` with the matching example file.
-- The SQLite lightweight mode runs a single `codex2api` container and stores data at `/data/codex2api.db`.
-- **SQLite compose files bind to `127.0.0.1` by default for security.** To expose the SQLite service on all interfaces, set `BIND_HOST=0.0.0.0` in `.env` or override the port binding in the compose file. The standard compose files bind to `0.0.0.0` by default.
-- The image studio library is stored under `/data/images`; uploaded admin backgrounds are stored under `/data/backgrounds`; Docker configurations persist `/data`.
-- `docker compose down` does not delete named volumes by default. Data is removed only by commands such as `docker compose down -v`, `docker volume rm`, or `docker volume prune`.
-
----
-
-## Antigravity channel (experimental API Key path)
-
-Antigravity accounts are managed as a dedicated Google channel with browser/imported OAuth credentials and an optional Google API Key credential shape. Admin tooling includes secret-bearing JSON/ZIP credential export plus sanitized state, explicit control-plane sync, and bounded capability probing. OAuth requests use the Cloud Code `v1internal` adapter. API Key requests target the Generative Language `v1beta/interactions` endpoint, but ordinary API-key dispatch is fail-closed by default and requires `ANTIGRAVITY_ENABLE_EXPERIMENTAL_INTERACTIONS=true`. The opt-in real-upstream integration test has not succeeded in this environment, so this path remains experimental rather than production-certified. See [docs/ANTIGRAVITY.md](docs/ANTIGRAVITY.md) for endpoints, test instructions, models, channel restrictions, plaintext credential-storage risk, and the certification checklist.
-
-## Documentation
-
-| Document | Description | Path |
-| --- | --- | --- |
-| [Chinese README](README.zh-CN.md) | Main Chinese project overview | `README.zh-CN.md` |
-| [Usage Guide](docs/USAGE.md) | Client setup, SDK examples, media workflows, and troubleshooting | `docs/USAGE.md` |
-| [API Documentation](docs/API.md) | API endpoints, request and response examples, error codes | `docs/API.md` |
-| [Antigravity Integration](docs/ANTIGRAVITY.md) | Google OAuth and experimental API Key channel, models, risks, and protocol status | `docs/ANTIGRAVITY.md` |
-| [Deployment Guide](docs/DEPLOYMENT.md) | Deployment modes, upgrade guide, backup and restore | `docs/DEPLOYMENT.md` |
-| [Configuration Guide](docs/CONFIGURATION.md) | Environment variables, system settings, configuration priority | `docs/CONFIGURATION.md` |
-| [Architecture](docs/ARCHITECTURE.md) | System architecture, scheduling algorithm, storage design | `docs/ARCHITECTURE.md` |
-| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common issues, diagnostic scripts, fixes | `docs/TROUBLESHOOTING.md` |
-| [Contributing](docs/CONTRIBUTING.md) | Development rules, PR workflow, code standards | `docs/CONTRIBUTING.md` |
+- Admin dashboard: http://localhost:8080/admin/
+- Health check: http://localhost:8080/health
----
+Named volumes are preserved by docker compose down. Use docker compose down -v only when you intentionally want to remove persisted data.
-## Upgrade and Local Development
+## Upgrade and local development
-Upgrade the standard image deployment:
+Upgrade a running image deployment:
-```bash
-git pull && docker compose pull && docker compose up -d && docker compose logs -f codex2api
-```
+~~~bash
+git pull
+docker compose pull
+docker compose up -d
+~~~
-Back up the database before upgrading:
+Back up PostgreSQL before an upgrade:
-```bash
+~~~bash
docker exec codex2api-postgres pg_dump -U codex2api codex2api > backup_$(date +%Y%m%d_%H%M%S).sql
-```
-
-Restore from a backup if needed:
-
-```bash
-docker exec -i codex2api-postgres psql -U codex2api codex2api < backup_xxx.sql
-```
-
-Unless you explicitly need to recreate resources, avoid `docker compose down` during upgrades. `pull + up -d` keeps existing containers and named volumes.
+~~~
-### Local Development
+The frontend must be built before the first backend run because Go embeds frontend/dist:
-Backend:
-
-```bash
+~~~bash
cp .env.example .env
cd frontend && npm ci && npm run build && cd ..
go run .
-```
-
-The frontend must be built before the first backend run because Go embeds `frontend/dist` through `go:embed`.
+~~~
-Frontend dev server:
+For frontend development:
-```bash
+~~~bash
cd frontend && npm ci && npm run dev
-```
+~~~
-Vite proxies `/api` and `/health` to the backend. During development, open `http://localhost:5173/admin/`.
-
----
+Open http://localhost:5173/admin/ during frontend development.
## Configuration
-### Environment Variables
-
-> For the full configuration reference, see [CONFIGURATION.md](docs/CONFIGURATION.md).
+The standard .env.example uses PostgreSQL and Redis. The SQLite mode uses .env.sqlite.example.
| Variable | Description |
| --- | --- |
-| `CODEX_PORT` | HTTP port, default `8080` |
-| `CODEX_MAX_REQUEST_BODY_SIZE_MB` | HTTP request body limit in MB, default `48` |
-| `ADMIN_SECRET` | Admin dashboard secret. When set, `/admin` prompts for authentication |
-| `DATABASE_DRIVER` | Database driver: `postgres` or `sqlite` |
-| `DATABASE_PATH` | SQLite database file path, used when `DATABASE_DRIVER=sqlite` |
-| `DATABASE_HOST` | PostgreSQL host |
-| `DATABASE_PORT` | PostgreSQL port, default `5432` |
-| `DATABASE_USER` | PostgreSQL user |
-| `DATABASE_PASSWORD` | PostgreSQL password |
-| `DATABASE_NAME` | PostgreSQL database name |
-| `DATABASE_SSLMODE` | PostgreSQL SSL mode, default `disable` |
-| `CACHE_DRIVER` | Cache driver: `redis` or `memory` |
-| `REDIS_ADDR` | Redis address, for example `redis:6379`, `redis://default:pass@host:6379/0`, or `rediss://default:pass@host:6379/0` |
-| `REDIS_USERNAME` | Optional Redis ACL username |
-| `REDIS_PASSWORD` | Redis password |
-| `REDIS_DB` | Redis database number |
-| `REDIS_TLS` | Enable TLS for `host:port` Redis addresses |
-| `REDIS_INSECURE_SKIP_VERIFY` | Skip Redis TLS certificate verification, default `false` |
-| `TZ` | Timezone, for example `Asia/Shanghai` |
-
-Cloud Redis providers such as Aiven and Upstash often require TLS. Prefer a `rediss://...` URL when your provider gives one.
-
-The standard `.env.example` declares `DATABASE_DRIVER=postgres` and `CACHE_DRIVER=redis`. For the lightweight SQLite mode, use `.env.sqlite.example`.
-
-### Runtime Settings
-
-Runtime business settings are stored in the database `SystemSettings` table and can be updated from the admin settings page.
-
-Examples include `MaxConcurrency`, `GlobalRPM`, `TestModel`, `TestContent`, `TestConcurrency`, `ProxyURL`, `PgMaxConns`, `RedisPoolSize`, `AdminSecret`, `SchedulerMode`, and auto-cleanup switches.
-
-Default settings are written automatically on first startup.
-
-#### Response Context Cache
-
-Locally reconstructed HTTP Responses continuations that use `previous_response_id` are protected by a bounded, per-process L1 cache. Its defaults are 64 MiB of logical retained JSON payload, 8 MiB per admitted entry, 2,000 entries, a 10-minute absolute TTL, and at most 200 raw items per entry.
-
-The Settings page exposes three persisted integer-MiB budgets:
-
-| Budget | Default | Allowed Range |
-| --- | --- | --- |
-| Local L1 total | 64 MiB | 8-4096 MiB |
-| Local L1 entry admission | 8 MiB | 1-256 MiB and no greater than the total |
-| Backend reconstruction | 64 MiB | 8-512 MiB |
-
-With Redis, a shared context that is within the reconstruction limit but above the L1 admission budget can still serve the request; it is not promoted into the local cache. Memory mode has no shared response-context fallback, so a dependent continuation whose context was oversized or evicted can return HTTP `409 response_context_unavailable`. A dependent continuation can return HTTP `503` when its shared backend is temporarily unavailable and no eligible relay fallback can preserve `previous_response_id`.
-
-Each successful budget change receives a read-only generation and is polled by every instance every five seconds. Operations shows effective/applied generations, synchronization state, logical cache bytes and counters, process memory, Go heap fields, and GC count. Logical cache bytes do not include Go/container overhead and are not an RSS or process-memory hard limit. During a rolling upgrade, a newer frontend tolerates an older backend that omits the new settings or Operations fields.
-
-### API Keys and Admin Secret
-
-- Public API keys come from the database API Keys table. If no key is configured, `/v1/*` skips API key authentication.
-- Admin Secret priority:
- - If `ADMIN_SECRET` is set in `.env`, the environment variable wins.
- - Otherwise, the database `AdminSecret` value is used.
- - After login, the frontend sends `X-Admin-Key` when calling `/api/admin/*`.
-
----
-
-## Public API
-
-| Endpoint | Description |
-| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
-| `POST /v1/chat/completions` | Chat Completions style endpoint |
-| `POST /v1/responses` | Responses style endpoint |
-| `POST /v1/images/generations` | OpenAI Images generation endpoint (gpt-image-2 / gpt-image-2.5 via Codex, grok-imagine via Grok) |
-| `POST /v1/images/edits` | OpenAI Images edit endpoint |
-| `POST /v1/videos/generations` | Grok Imagine video generation (async, returns `request_id`) |
-| `POST /v1/videos/edits` / `POST /v1/videos/extensions` | Grok Imagine video edit / extension |
-| `GET /v1/videos/:id` | Poll video task status (`video.url` rewritten to the gateway content proxy) |
-| `GET /v1/videos/:id/content` | Download the generated video through the gateway (Range supported) |
-| `GET /v1/models` | List available models (includes gpt-6-astra/sol/luna, gpt-5.6-sol/terra/luna, gpt-5.5, gpt-5.3-codex-spark, gpt-image-2, grok-imagine-*, etc.) |
-| `GET /health` | Health check |
-
-> **Pricing**: gpt-5.5 is billed at $5.00/M input and $30.00/M output (standard tier). Priority tier: $12.50/M input, $75.00/M output. Other models follow pricing rules in the billing engine.
-
-See [API.md](docs/API.md) for full request formats, response formats, and error codes.
-
-### Token Upload and Account Management
-
-The following admin endpoints require the `X-Admin-Key` header.
-
-#### Add Refresh Token Accounts
-
-```bash
-# Single account
-curl -X POST http://localhost:8080/api/admin/accounts \
- -H "X-Admin-Key: your-admin-secret" \
- -H "Content-Type: application/json" \
- -d '{"name": "my-account", "refresh_token": "rt_xxxxxxxxxxxx"}'
-
-# Batch import, newline separated, up to 100 tokens per request
-curl -X POST http://localhost:8080/api/admin/accounts \
- -H "X-Admin-Key: your-admin-secret" \
- -H "Content-Type: application/json" \
- -d '{"name": "batch", "refresh_token": "rt_xxx1\nrt_xxx2\nrt_xxx3"}'
-```
-
-#### Add Access Token Accounts
-
-```bash
-# Single AT-only account
-curl -X POST http://localhost:8080/api/admin/accounts/at \
- -H "X-Admin-Key: your-admin-secret" \
- -H "Content-Type: application/json" \
- -d '{"name": "my-at", "access_token": "eyJhbGciOiJSUzI1NiIs..."}'
-
-# Batch import, newline separated
-curl -X POST http://localhost:8080/api/admin/accounts/at \
- -H "X-Admin-Key: your-admin-secret" \
- -H "Content-Type: application/json" \
- -d '{"access_token": "eyJtoken1...\neyJtoken2...\neyJtoken3..."}'
-```
-
-#### File Import
-
-```bash
-# Import Refresh Tokens from TXT, one token per line
-curl -X POST http://localhost:8080/api/admin/accounts/import \
- -H "X-Admin-Key: your-admin-secret" \
- -F "file=@tokens.txt" \
- -F "format=txt"
-
-# Import Refresh Tokens from JSON
-curl -X POST http://localhost:8080/api/admin/accounts/import \
- -H "X-Admin-Key: your-admin-secret" \
- -F "file=@credentials.json" \
- -F "format=json"
-
-# Import Access Tokens from TXT, one token per line
-curl -X POST http://localhost:8080/api/admin/accounts/import \
- -H "X-Admin-Key: your-admin-secret" \
- -F "file=@access_tokens.txt" \
- -F "format=at_txt"
-```
-
-Import endpoints deduplicate tokens automatically. Existing tokens are not inserted again.
-
-#### OAuth PKCE Authorization
-
-Codex2API supports acquiring Refresh Tokens through the OAuth PKCE flow, useful when manual token extraction is impractical:
-
-```bash
-# Step 1: Generate an authorization URL
-curl -X POST http://localhost:8080/api/admin/oauth/generate-auth-url \
- -H "X-Admin-Key: your-admin-secret" \
- -H "Content-Type: application/json" \
- -d '{}'
-
-# Step 2: Open the returned auth_url in a browser, complete authorization
-# Step 3: Exchange the authorization code for a token (auto-creates account)
-curl -X POST http://localhost:8080/api/admin/oauth/exchange-code \
- -H "X-Admin-Key: your-admin-secret" \
- -H "Content-Type: application/json" \
- -d '{"session_id": "...", "code": "...", "state": "..."}'
-```
-
-See [API.md](docs/API.md) for the full OAuth flow and all admin endpoints.
-
----
-
-## Admin Dashboard
-
-Open `/admin/` in a browser.
-
-| Page | Path | Description |
-| --- | --- | --- |
-| Dashboard | `/admin/` | Overview metrics, request trends, latency trends, token breakdown, model ranking |
-| Accounts | `/admin/accounts` | Import, test, batch actions, scheduler state |
-| API Keys | `/admin/api-keys` | API key creation, inspection, deletion, and credential management |
-| Proxies | `/admin/proxies` | Proxy pool management, account proxy assignment, connectivity checks |
-| Image Studio | `/admin/images/studio` | Text-to-image, image-to-image, prompt templates, task history, server-side image library |
-| Image Studio portal (non-admin) | `/image-studio` | Standalone studio for teammates using their own API key; toggle on the API Keys page |
-| Prompt Filter | `/admin/prompt-filter/overview` | Rules, hit logs, testing, and handling mode configuration |
-| Usage | `/admin/usage` | Request logs, metric cards, charts, log cleanup |
-| Operations | `/admin/ops` | Runtime overview, response-context logical cache metrics, process memory, Go heap, and GC |
-| Scheduler Board | `/admin/ops/scheduler` | Scheduler health, penalties, and score breakdown |
-| Settings | `/admin/settings` | Runtime parameters, response-context cache budgets, and admin secret settings |
-| Usage Guide | `/admin/docs` | Codex CLI and Claude Code integration examples |
-| API Reference | `/admin/api-reference` | OpenAI-style endpoints and admin API reference |
-
----
-
-## Core Capabilities
-
-### Positioning
-
-Codex2API is not just a forwarding proxy. It is a long-running Codex gateway with a full admin dashboard:
-
-- Exposes a unified OpenAI-style API surface.
-- Maintains a Refresh Token account pool and Access Token lifecycle.
-- Coordinates persistence and runtime state through PostgreSQL + Redis or SQLite + in-memory cache.
-- Provides operational observability through the `/admin` dashboard.
-
-### Request Flow
-
-Public request flow:
-
-```text
-Client -> Gin RPM limiter -> proxy.Handler API key check -> auth.Store scheduler -> upstream request -> response + usage logging
-```
-
-Admin flow:
-
-```text
-Browser -> embedded /admin frontend -> /api/admin/* -> database / account pool / cache layer
-```
-
-### Scheduler
-
-The scheduler lives in `auth.Store`. It evaluates availability, scheduler priority, health tier, dynamic concurrency, historical errors, and recent usage before selecting an account.
-
-Runtime state:
-
-- `Status`: `ready`, `cooldown`, `error`
-- `HealthTier`: `healthy`, `warm`, `risky`, `banned`
-- `SchedulerScore`: real-time scheduling score based on a baseline of 100
-- `DynamicConcurrencyLimit`: concurrency limit adjusted by health tier
-- `SchedulerPriority`: strict account priority; higher-priority accounts are considered before health tier, score, or current load
-
-Selection strategy:
-
-1. Filter unavailable accounts, including `error`, `banned`, cooldown accounts, and accounts without an Access Token.
-2. Recompute health tier, scheduler score, and dynamic concurrency.
-3. Exclude accounts that have reached their concurrency limit.
-4. Prefer higher `SchedulerPriority`, then `healthy > warm > risky > banned`; within the same priority and tier, prefer higher score and lower concurrency.
-5. In indexed mode, use a per-tier cursor or deterministic affinity offset inside the highest valid priority/health segment.
-
-When multiple end users share one downstream API key, send `X-Codex2API-Affinity-Key` with a stable user or conversation identifier. Codex2API hashes it for local account affinity only and never forwards it upstream.
-
-Concurrency rules:
-
-| Tier | Concurrency Limit |
-| --- | --- |
-| `healthy` | System `MaxConcurrency` |
-| `warm` | Base concurrency / 2, at least 1 |
-| `risky` | Fixed at 1 |
-| `banned` | Fixed at 0, not schedulable |
-
-The persistent upstream WebSocket pool is also capped by each account's current `DynamicConcurrencyLimit`, so connection reuse cannot grow beyond the account's effective concurrency.
-
-Observability:
-
-- `GET /api/admin/accounts` shows health tier, scheduler score, and penalty details.
-- `GET /api/admin/ops/overview` shows scheduler engine, indexed/legacy selections, scan volume, event waiters, sparse routing-cache state, shadow parity, and outbox lag in addition to runtime and connection-pool state.
-- `/admin/ops/scheduler` provides the scheduler board.
-
-**Scheduler engine** (`scheduler_engine`, via Admin Settings, or `CODEX_SCHEDULER_ENGINE`):
-
-| Engine | Behavior |
+| CODEX_PORT | HTTP port, default 8080 |
+| BIND_HOST | Listen address, for example 127.0.0.1 or 0.0.0.0 |
+| ADMIN_SECRET | Admin dashboard login secret |
+| DATABASE_DRIVER | postgres or sqlite |
+| DATABASE_PATH | SQLite database path when DATABASE_DRIVER=sqlite |
+| DATABASE_HOST / DATABASE_PORT | PostgreSQL connection address |
+| DATABASE_USER / DATABASE_PASSWORD / DATABASE_NAME | PostgreSQL credentials and database |
+| CACHE_DRIVER | redis or memory |
+| REDIS_ADDR | Redis address or URL |
+| TZ | IANA timezone, for example Asia/Shanghai |
+
+Business settings such as scheduler mode, request limits and billing options are stored in the database and managed from the admin console. See [docs/CONFIGURATION.md](docs/CONFIGURATION.md) for the complete reference.
+
+## API and administration
+
+| Endpoint | Description |
| --- | --- |
-| `legacy` | Compatibility path that scans the immutable account snapshot |
-| `shadow` | Legacy remains authoritative while 1 in 64 requests compares indexed candidate availability |
-| `indexed` | Priority/health buckets, sparse API-key sub-pools, and event-driven availability waits are authoritative |
-
-For a production rollout, use `legacy → shadow → indexed`. `CODEX_SCHEDULER_ENGINE` overrides the database setting and can pin an instance for a canary or emergency rollback. The old `FAST_SCHEDULER_ENABLED=true` switch remains a compatibility alias for `indexed` when no engine is configured.
-
-**Scheduler mode** (`scheduler_mode`, via Admin Settings):
-
-| Mode | Behavior |
-| --- | --- |
-| `round_robin` (default) | Round-robin across available accounts per health tier, weighted by dispatch score |
-| `remaining_quota` | Prioritizes accounts with lower usage percent; round-robin for ties |
-| `fill_first` | Keeps draining the account with the least remaining quota until it is exhausted or rate-limited, then falls to the next (A → B → C) |
-
-**Credit accounts** (per-account flags):
-
-When an account has a credit-based billing model instead of a usage-based Free/Pro plan, you can mark it so the scheduler skips usage-window penalties:
-
-| Field | Type | Effect |
-| --- | --- | --- |
-| `credit_enabled` | bool | Mark account as credit-based billing |
-| `credit_skip_usage_window` | bool | When true, skip 7d/5h usage-window penalties for this account |
+| POST /v1/chat/completions | OpenAI-compatible Chat Completions |
+| POST /v1/responses | Responses API |
+| POST /v1/messages | Anthropic Messages API |
+| POST /v1/images/generations | Image generation |
+| GET /v1/models | Available models |
+| GET /health | Health check |
-**Windowed USD cost**: The accounts table displays per-account billed cost over two windows -- the past 5 hours and the past 7 days -- aligned with each account's usage reset boundaries. This shows actual spending per account rather than estimated token costs.
+The main administration pages are /admin/accounts, /admin/api-keys, /admin/usage, /admin/channel-monitors, /admin/settings and /admin/ops. Public API keys and the admin secret are configured from the administration console.
----
+Pricing uses the model pricing table and the custom multiplier state described in [Custom maintenance](#custom-maintenance). A failed or unavailable multiplier probe falls back to the official model price.
-## Project Structure
-
-```text
-codex2api/
-|- main.go # Application entrypoint
-|- Dockerfile # Multi-stage image build
-|- docker-compose.yml # Image deployment template
-|- docker-compose.local.yml # Local source build template
-|- .env.example # Environment variable example
-|- admin/ # Admin API
-|- auth/ # Account pool, scheduler, token management
-|- cache/ # Redis and cache wrappers
-|- config/ # Environment loading
-|- database/ # Database access layer
-|- proxy/ # Public proxy, forwarding, rate limiting
-`- frontend/ # React + Vite admin dashboard
- |- src/pages/ # Dashboard / Accounts / API Keys / Proxies / Images / Prompt Filter / Ops / Usage / Settings / Docs
- |- src/components/ # UI components
- |- src/locales/ # zh/en locales
- `- vite.config.js # Vite config
-```
-
----
-
-## Notes
-
-- `docker-compose.yml` pulls the GHCR image for deployment. `docker-compose.local.yml` uses `build: .` for local source builds.
-- The frontend base path is fixed at `/admin/` for both local development and production.
-- Before manually building the Go binary, run `npm run build` in `frontend/`.
-- `.env` controls physical runtime settings such as port, database, and Redis. Business settings are stored in the database and managed from the admin dashboard.
-- API keys are stored in the database and configured through the admin dashboard.
-
----
-
-## Community
-
-- QQ group: [Join the "codex2api" group chat](https://qun.qq.com/universal-share/share?ac=1&authKey=6vwawW4MeqdACT7PajnHlf2lLkjfuNXEMSos67l9FBiAJ8t%2BKeaXJXB0dgsnhFa1&busi_data=eyJncm91cENvZGUiOiI4MTY3Mzk4NDIiLCJ0b2tlbiI6ImU1YW1KR3dNaXZoUXZDUWpYTWVncmdmMXhQV1RwQ21tbEhkdjB5VW45aWVPSjhFM2grMkRHNGdhWnhEU29oS08iLCJ1aW4iOiIxMTYzNDc2OTQ5In0%3D&data=adSomD6r40Al25rBr8PocFCKumQR5oxi1kq5jXjXxeJ49Z5cj4QLzbNf6vfIQKWMORrJntrZtcoyQuHg2ksUeA&svctype=4&tempid=h5_group_info) (group ID: 816739842)
-- Telegram group: [Join the Telegram group](https://t.me/+9hJAA3ZWQxxmMzE5)
-
-Join the group to discuss deployment, usage, and development questions.
-
----
-
-## Disclaimer and License
-
-- This project is for learning, research, and technical discussion only.
-- This project is released under the `MIT License`.
-- The project provides no warranty for direct or indirect consequences. Production use is at your own risk.
-
----
-
-## Star History
-
-
- | 统一兼容入口 | 同时覆盖 OpenAI 风格 Chat Completions / Responses / Images、Anthropic Messages、无前缀兼容路由和 Codex 原生 Responses 转发,客户端侧少改配置即可接入。 |
| 账号池调度核心 | 围绕账号状态、健康层级、调度分、动态并发、冷却恢复和近期用量做选择,自动避开不可用账号,减少单账号打满和反复失败。支持 round_robin 和 remaining_quota 两种调度模式,以及单账号信用计费标记。 |
| 可视化管理后台 | 内置 React / Vite 管理台,提供账号导入测试、API Key、代理池、生图(文生图 + 图生图)、Prompt 检查、用量统计、运维概览、调度看板和系统设置。 |
| 两种部署形态 | 生产环境用 PostgreSQL + Redis,单机测试用 SQLite + Memory;Docker 镜像、源码构建、本地开发和一键交互部署脚本都已准备好。SQLite 模式默认绑定 127.0.0.1 以提升安全性。 |
| 计费与可观测性 | 单账号 5h/7d 窗口化 USD 费用追踪、信用配额支持、API Key 用量追踪、OAuth PKCE 获取 Token、Prompt 过滤,以及含请求日志与趋势图表的用量仪表盘。 |
docker-compose.yml | 服务器和测试环境,推荐使用 |
+| 本地源码构建 | docker-compose.local.yml | 构建并验证当前源码 |
+| SQLite 镜像 | docker-compose.sqlite.yml | 不依赖 PostgreSQL / Redis 的单机部署 |
+| SQLite 源码构建 | docker-compose.sqlite.local.yml | 验证轻量 SQLite 模式 |
+| 本地开发 | go run . + npm run dev | 前后端开发调试 |
-标准镜像版:
+### 标准部署
-```bash
-git clone https://github.com/james-6-23/codex2api.git
+~~~bash
+git clone --branch codex2api-custom https://github.com/JayHome137/codex2api.git
cd codex2api
cp .env.example .env
docker compose pull
docker compose up -d
docker compose logs -f codex2api
-```
+~~~
-标准本地构建版:
+### 本地源码构建
-```bash
+~~~bash
cp .env.example .env
docker compose -f docker-compose.local.yml up -d --build
docker compose -f docker-compose.local.yml logs -f codex2api
-```
+~~~
-SQLite 镜像版:
+### SQLite 部署
-```bash
+~~~bash
cp .env.sqlite.example .env
docker compose -f docker-compose.sqlite.yml pull
docker compose -f docker-compose.sqlite.yml up -d
docker compose -f docker-compose.sqlite.yml logs -f codex2api
-```
+~~~
-SQLite 本地构建版:
-
-```bash
-cp .env.sqlite.example .env
-docker compose -f docker-compose.sqlite.local.yml up -d --build
-docker compose -f docker-compose.sqlite.local.yml logs -f codex2api
-```
-
-补充说明:
-
-- 标准版和 SQLite 版都读取 `.env`
-- 切换部署模式前,需要先用对应的示例文件覆盖当前 `.env`
-- 标准镜像版项目名固定为 `codex2api`,数据卷固定为 `codex2api_pgdata`、`codex2api_redisdata`
-- 标准本地构建版项目名固定为 `codex2api-local`,数据卷固定为 `codex2api-local_pgdata`、`codex2api-local_redisdata`
-- SQLite 镜像版项目名固定为 `codex2api-sqlite`,数据卷固定为 `codex2api-sqlite_sqlite-data`
-- SQLite 本地构建版项目名固定为 `codex2api-sqlite-local`,数据卷固定为 `codex2api-sqlite-local_sqlite-data-local`
-- 标准版容器名:`codex2api`
-- SQLite 镜像版容器名:`codex2api-sqlite`
-- SQLite 本地构建版容器名:`codex2api-sqlite-local`
-- SQLite 轻量版只启动 `codex2api` 单容器,数据保存在 `/data/codex2api.db`
-- **SQLite compose 文件默认绑定 `127.0.0.1`,仅本机可访问。** 如需暴露给外部,请在 `.env` 中设置 `BIND_HOST=0.0.0.0` 或修改 compose 文件中的端口绑定。标准版 compose 文件默认绑定 `0.0.0.0`(所有网络接口)。
-- 生图工作台图库默认保存在 `/data/images`,上传的后台背景默认保存在 `/data/backgrounds`,标准版和 SQLite 版 Docker 配置都会持久化 `/data`
-- `docker compose down` 默认不会删除命名卷;只有 `docker compose down -v`、`docker volume rm` 或 `docker volume prune` 才会删除持久化数据
-- 不同部署模式的数据卷彼此隔离;切换 compose 文件后看到空数据,通常是切到了另一组卷,而不是原卷被自动删除
+SQLite compose 文件默认绑定 127.0.0.1。需要外部访问时,在 .env 中设置 BIND_HOST=0.0.0.0。标准 compose 文件默认监听所有网络接口。
启动后访问:
-- 管理台:`http://localhost:8080/admin/`
-- 健康检查:`http://localhost:8080/health`
-
-> 更多部署详情请参考:[DEPLOYMENT.md](docs/DEPLOYMENT.md)
-
----
+- 管理后台:http://localhost:8080/admin/
+- 健康检查:http://localhost:8080/health
-## Antigravity 渠道(API Key 路径为实验性)
-
-Antigravity 作为独立 Google 渠道管理,支持浏览器/导入 OAuth 凭据以及 Google API Key 账号。管理端提供含密钥的 JSON/ZIP 凭据导出、脱敏状态读取、显式控制面同步与有界能力探测。OAuth 请求使用 Cloud Code `v1internal` 适配器。API Key 请求指向 Generative Language `v1beta/interactions`,但普通调度默认关闭,只有显式设置 `ANTIGRAVITY_ENABLE_EXPERIMENTAL_INTERACTIONS=true` 才会放行。当前环境尚未成功运行真实上游集成测试,因此 API Key 路径仍为实验性,不能宣称已具备生产可用性。运行方法、安全风险与认证清单见 [docs/ANTIGRAVITY.md](docs/ANTIGRAVITY.md)。
-
-## 完整文档
-
-| 文档 | 说明 | 路径 |
-|------|------|------|
-| [API 文档](docs/API.md) | 所有 API 端点、请求/响应示例、错误码说明 | `docs/API.md` |
-| [使用指南](docs/USAGE.md) | 客户端接入、SDK 示例、媒体任务与常见错误排查 | `docs/USAGE.md` |
-| [Antigravity 接入](docs/ANTIGRAVITY.md) | Google OAuth、实验性 API Key 渠道、模型、风险与协议验证状态 | `docs/ANTIGRAVITY.md` |
-| [部署文档](docs/DEPLOYMENT.md) | 各种部署模式、升级指南、备份恢复 | `docs/DEPLOYMENT.md` |
-| [配置文档](docs/CONFIGURATION.md) | 环境变量、系统设置、配置优先级 | `docs/CONFIGURATION.md` |
-| [架构文档](docs/ARCHITECTURE.md) | 系统架构、调度算法、存储设计 | `docs/ARCHITECTURE.md` |
-| [故障排查](docs/TROUBLESHOOTING.md) | 常见问题排查、诊断脚本、解决方案 | `docs/TROUBLESHOOTING.md` |
-| [贡献指南](docs/CONTRIBUTING.md) | 开发规范、PR 流程、代码标准 | `docs/CONTRIBUTING.md` |
-| [English README](README.md) | 英文项目介绍、部署和后台功能概览 | `README.md` |
-
----
+docker compose down 默认会保留命名卷。只有在明确需要删除持久化数据时,才使用 docker compose down -v。
## 升级与本地开发
-```bash
-git pull && docker compose pull && docker compose up -d && docker compose logs -f codex2api
-```
+升级正在运行的镜像部署:
-> **⚠️ 重要:升级前请先备份数据库!**
->
-> ```bash
-> docker exec codex2api-postgres pg_dump -U codex2api codex2api > backup_$(date +%Y%m%d_%H%M%S).sql
-> ```
->
-> 如果升级后数据异常,可通过以下命令恢复:
->
-> ```bash
-> docker exec -i codex2api-postgres psql -U codex2api codex2api < backup_xxx.sql
-> ```
+~~~bash
+git pull
+docker compose pull
+docker compose up -d
+~~~
-如非必要,不建议在升级时执行 `docker compose down`;标准升级直接 `pull + up -d` 即可复用现有容器和命名卷。
+升级前备份 PostgreSQL:
-### 本地开发模式
+~~~bash
+docker exec codex2api-postgres pg_dump -U codex2api codex2api > backup_$(date +%Y%m%d_%H%M%S).sql
+~~~
-**后端:**
+首次运行后端前,需要先构建前端,因为 Go 会通过 go:embed 嵌入 frontend/dist:
-```bash
+~~~bash
cp .env.example .env
cd frontend && npm ci && npm run build && cd ..
go run .
-```
-
-> 首次启动需要先构建前端,因为 Go 使用 `go:embed` 嵌入 `frontend/dist` 。
+~~~
-**前端开发服务器(联调):**
+前端开发服务器:
-```bash
+~~~bash
cd frontend && npm ci && npm run dev
-```
+~~~
-Vite 会自动代理 `/api` 和 `/health` 到后端,开发时访问 `http://localhost:5173/admin/`。
-
----
+前端开发时访问 http://localhost:5173/admin/。
## 环境配置
-### `.env` 环境变量
-
-> 完整配置说明请参考:[CONFIGURATION.md](docs/CONFIGURATION.md)
+标准 .env.example 使用 PostgreSQL 和 Redis,SQLite 模式使用 .env.sqlite.example。
| 变量 | 说明 |
| --- | --- |
-| `CODEX_PORT` | HTTP 端口,默认 `8080` |
-| `CODEX_MAX_REQUEST_BODY_SIZE_MB` | HTTP 请求体上限,单位 MB,默认 `48` |
-| `ADMIN_SECRET` | 管理后台登录密钥;设置后首次访问 `/admin` 会弹出密码输入框 |
-| `DATABASE_DRIVER` | 数据库驱动,支持 `postgres` / `sqlite` |
-| `DATABASE_PATH` | SQLite 数据文件路径,`DATABASE_DRIVER=sqlite` 时生效 |
-| `DATABASE_HOST` | PostgreSQL 主机,`DATABASE_DRIVER=postgres` 时生效 |
-| `DATABASE_PORT` | PostgreSQL 端口,默认 `5432` |
-| `DATABASE_USER` | PostgreSQL 用户 |
-| `DATABASE_PASSWORD` | PostgreSQL 密码 |
-| `DATABASE_NAME` | PostgreSQL 数据库名 |
-| `DATABASE_SSLMODE` | PostgreSQL SSL 模式,默认 `disable` |
-| `CACHE_DRIVER` | 缓存驱动,支持 `redis` / `memory` |
-| `REDIS_ADDR` | Redis 地址,例如 `redis:6379`、`redis://default:pass@host:6379/0`、`rediss://default:pass@host:6379/0`,`CACHE_DRIVER=redis` 时生效 |
-| `REDIS_USERNAME` | Redis ACL 用户名,可选;URL 中带用户名时可不填 |
-| `REDIS_PASSWORD` | Redis 密码 |
-| `REDIS_DB` | Redis DB 库号 |
-| `REDIS_TLS` | 是否为 `host:port` 形式的 Redis 启用 TLS;使用 `rediss://` 时会自动启用 |
-| `REDIS_INSECURE_SKIP_VERIFY` | 跳过 Redis TLS 证书校验,默认 `false`,仅用于自签证书或排障 |
-| `TZ` | 时区,例如 `Asia/Shanghai` |
-
-> Aiven、Upstash 等云 Redis 通常要求 TLS。推荐直接将 `REDIS_ADDR` 配置为平台提供的 `rediss://...` URL;如果只填写 `host:port`,请同时设置 `REDIS_TLS=true`。
-
-标准版 `.env.example` 已显式声明 `DATABASE_DRIVER=postgres` 与 `CACHE_DRIVER=redis`;SQLite 轻量版请改用 `.env.sqlite.example`。
-
-### 业务运行配置
-
-以下参数**保存在数据库 `SystemSettings` 中**,通过管理台设置页面修改:
-
-`MaxConcurrency`、`GlobalRPM`、`TestModel`、`TestContent`、`TestConcurrency`、`ProxyURL`、`PgMaxConns`、`RedisPoolSize`、`AdminSecret`、`SchedulerMode`、自动清理开关等。
-
-首次启动时程序会自动写入默认设置。
-
-#### Responses 上下文缓存
-
-使用 `previous_response_id` 并在本地重建的 HTTP Responses 连续请求由每个进程内的有界 L1 缓存保护。默认保存 64 MiB 逻辑 JSON payload,单条 L1 准入上限为 8 MiB,最多 2,000 条,绝对 TTL 为 10 分钟,每条最多保留 200 个 raw item。
-
-设置页提供三个持久化的整数 MiB 预算:
-
-| 预算 | 默认值 | 可选范围 |
-| --- | --- | --- |
-| 本地 L1 总量 | 64 MiB | 8-4096 MiB |
-| 本地 L1 单条准入 | 8 MiB | 1-256 MiB,且不能超过总量 |
-| 后端重建 | 64 MiB | 8-512 MiB |
-
-Redis 模式下,共享上下文只要没有超过重建上限,即使大于 L1 准入预算也能直接服务本次请求,但不会提升到本地缓存。Memory 模式没有共享 response context 后备;依赖上下文被判定为超限或已淘汰时,连续请求可能返回 HTTP `409 response_context_unavailable`。共享后端暂时故障且没有可保留 `previous_response_id` 的 relay 后备账号时,依赖上下文的连续请求可能返回 HTTP `503`。
-
-每次成功修改预算都会生成只读 generation,各实例每 5 秒轮询一次并应用更新。运维页展示 effective/applied generation、同步状态、缓存逻辑字节与计数器、进程内存、Go heap 和 GC 次数。缓存逻辑字节不包含 Go/容器开销,也不是 RSS 或进程内存硬上限。滚动升级期间,新前端会兼容尚未返回这些设置或运维字段的旧后端。
-
-### API Key 与管理密钥
-
-- **对外 API Key**:以数据库中的 API Keys 为准。如果没有配置任何 Key,则 `/v1/*` 跳过鉴权。
-- **管理后台 Admin Secret**:
- - 如果 `.env` 中设置了 `ADMIN_SECRET`,则优先使用环境变量。
- - 如果未设置 `ADMIN_SECRET`,则回退到数据库中的 `AdminSecret`。
- - 鉴权生效时,首次访问 `/admin` 会弹出密码输入框;前端登录成功后通过 `X-Admin-Key` 请求头访问 `/api/admin/*`。
-
----
-
-## 对外接口
-
-| 接口 | 说明 |
-| ----------------------------- | -------------------------------------------------------------------------------------------------------- |
-| `POST /v1/chat/completions` | Chat Completions 风格入口 |
-| `POST /v1/responses` | Responses 风格入口 |
-| `POST /v1/images/generations` | OpenAI Images 生成入口 |
-| `POST /v1/images/edits` | OpenAI Images 编辑入口 |
-| `GET /v1/models` | 返回可用模型列表(含 gpt-6-astra/sol/luna、gpt-5.6-sol/terra/luna、gpt-5.5、gpt-5.3-codex-spark、gpt-image-2 等) |
-| `GET /health` | 健康检查 |
-
-> **计费提示**:gpt-5.5 标准 tier 计费为 $5.00/M 输入 / $30.00/M 输出,priority tier 为 $12.50/M 输入 / $75.00/M 输出。其他模型按 billing 引擎规则计费。
-
-> 完整请求/响应格式、错误码参见 [API 文档](docs/API.md)。
-
-### Token 上传与账号管理
-
-以下接口需要 `X-Admin-Key` 认证头。
-
-#### 添加 Refresh Token 账号
-
-```bash
-# 单个添加
-curl -X POST http://localhost:8080/api/admin/accounts \
- -H "X-Admin-Key: your-admin-secret" \
- -H "Content-Type: application/json" \
- -d '{"name": "my-account", "refresh_token": "rt_xxxxxxxxxxxx"}'
-
-# 批量添加(换行分隔,单次最多 100 个)
-curl -X POST http://localhost:8080/api/admin/accounts \
- -H "X-Admin-Key: your-admin-secret" \
- -H "Content-Type: application/json" \
- -d '{"name": "batch", "refresh_token": "rt_xxx1\nrt_xxx2\nrt_xxx3"}'
-```
-
-#### 添加 Access Token 账号(AT-only)
-
-```bash
-# 单个添加
-curl -X POST http://localhost:8080/api/admin/accounts/at \
- -H "X-Admin-Key: your-admin-secret" \
- -H "Content-Type: application/json" \
- -d '{"name": "my-at", "access_token": "eyJhbGciOiJSUzI1NiIs..."}'
-
-# 批量添加(换行分隔)
-curl -X POST http://localhost:8080/api/admin/accounts/at \
- -H "X-Admin-Key: your-admin-secret" \
- -H "Content-Type: application/json" \
- -d '{"access_token": "eyJtoken1...\neyJtoken2...\neyJtoken3..."}'
-```
-
-#### 文件批量导入
-
-```bash
-# 导入 Refresh Token(TXT,每行一个)
-curl -X POST http://localhost:8080/api/admin/accounts/import \
- -H "X-Admin-Key: your-admin-secret" \
- -F "file=@tokens.txt" \
- -F "format=txt"
-
-# 导入 Refresh Token(JSON 格式)
-curl -X POST http://localhost:8080/api/admin/accounts/import \
- -H "X-Admin-Key: your-admin-secret" \
- -F "file=@credentials.json" \
- -F "format=json"
-
-# 导入 Access Token(AT-TXT,每行一个)
-curl -X POST http://localhost:8080/api/admin/accounts/import \
- -H "X-Admin-Key: your-admin-secret" \
- -F "file=@access_tokens.txt" \
- -F "format=at_txt"
-```
-
-> 所有导入接口自动去重,已存在的 Token 不会重复写入。更多管理接口(导出、迁移、OAuth 授权等)参见 [API 文档](docs/API.md)。
-
-#### OAuth PKCE 授权
-
-Codex2API 支持通过 OAuth PKCE 流程获取 Refresh Token,适用于无法手动提取 Token 的场景:
-
-```bash
-# 步骤 1:生成授权 URL
-curl -X POST http://localhost:8080/api/admin/oauth/generate-auth-url \
- -H "X-Admin-Key: your-admin-secret" \
- -H "Content-Type: application/json" \
- -d '{}'
-
-# 步骤 2:在浏览器中打开返回的 auth_url,完成授权
-# 步骤 3:用授权码兑换 Token(自动创建账号)
-curl -X POST http://localhost:8080/api/admin/oauth/exchange-code \
- -H "X-Admin-Key: your-admin-secret" \
- -H "Content-Type: application/json" \
- -d '{"session_id": "...", "code": "...", "state": "..."}'
-```
-
-> 完整 OAuth 流程及所有管理接口参见 [API 文档](docs/API.md)。
-
----
-
-## 管理后台
-
-浏览器访问 `/admin/`,提供以下页面:
-
-| 页面 | 路径 | 功能 |
-| --- | --- | --- |
-| Dashboard | `/admin/` | 总览指标、请求趋势、延迟趋势、Token 分布、模型排行 |
-| 账号管理 | `/admin/accounts` | 导入、测试、批量处理、调度信息查看 |
-| API 密钥 | `/admin/api-keys` | API Key 创建、查看、删除与调用凭据管理 |
-| 代理管理 | `/admin/proxies` | 代理池维护、账号代理分配与连通性管理 |
-| 生图工作台 | `/admin/images/studio` | 文生图、图生图、提示词模板、任务历史和服务器图库 |
-| 生图门户(非管理) | `/image-studio` | 用 API Key 登录的独立生图页,不进入管理后台;可在 API 密钥页开关 |
-| Prompt 检查 | `/admin/prompt-filter/overview` | Prompt 规则、触发日志、测试和处理模式配置 |
-| 使用统计 | `/admin/usage` | 请求日志、统计卡片、图表、日志清空 |
-| 运维概览 | `/admin/ops` | 运行态概览、上下文缓存逻辑指标、进程内存、Go heap 与 GC |
-| 调度看板 | `/admin/ops/scheduler` | 调度健康度、惩罚项和评分拆解 |
-| 系统设置 | `/admin/settings` | 业务运行参数、Responses 上下文缓存预算与后台密钥配置 |
-| 使用文档 | `/admin/docs` | Codex CLI / Claude Code 接入示例 |
-| API 文档 | `/admin/api-reference` | OpenAI 风格接口与管理接口参考 |
-
----
-
-## 核心能力
-
-### 项目定位
-
-这个项目不是单纯的接口转发,而是一套面向长期运行的 Codex 网关与管理后台:
-
-- 对外提供统一的 OpenAI 风格入口,屏蔽上游多账号差异
-- 对内维护基于 `Refresh Token` 的账号池、`Access Token` 生命周期和运行时调度
-- 通过 PostgreSQL + Redis 或 SQLite + 内存缓存实现配置持久化与运行态协调
-- 通过 `/admin` 管理台提供全面的运维观测能力
-
-### 架构概览
-
-**对外请求链路:** 客户端请求 → Gin RPM 限流 → `proxy.Handler` API Key 校验 → `auth.Store` 调度选号 → 上游请求 → 响应回传 + 用量写入
-
-**管理后台链路:** 浏览器 → `/admin/` 嵌入式前端 → `/api/admin/*` 管理接口 → 数据库 / 账号池 / 缓存层
-
-### 调度系统
-
-调度核心位于 `auth.Store`,将账号可用性、调度优先级、健康度、动态并发、历史错误和近期用量综合纳入选择。
-
-**运行时状态模型:**
-
-- `Status`:`ready` / `cooldown` / `error`
-- `HealthTier`:`healthy` / `warm` / `risky` / `banned`
-- `SchedulerScore`:以 100 为基线的实时调度分
-- `DynamicConcurrencyLimit`:按健康层级动态收缩的并发上限
-- `SchedulerPriority`:严格的账号优先级;先比较优先级,再比较健康层级、调度分和当前负载
-
-**账号选择策略:**
-
-1. 过滤不可用账号(error / banned / 冷却中 / 无 AccessToken)
-2. 重算健康层级、调度分和动态并发
-3. 排除已达并发上限的账号
-4. 先按 `SchedulerPriority` 从高到低分层,再按 `healthy > warm > risky > banned` 排序;同优先级、同层级内按调度分和并发数择优
-5. 15% 概率随机打散,降低热点与饥饿
-
-多个最终用户共享同一个下游 API Key 时,可传 `X-Codex2API-Affinity-Key` 作为稳定的用户或对话标识。Codex2API 只将其哈希后用于本地账号亲和,不会转发给上游。
-
-**动态并发规则:**
-
-| 层级 | 并发上限 |
-| --- | --- |
-| `healthy` | 系统 `MaxConcurrency` |
-| `warm` | 基础并发 ÷ 2(最少 1) |
-| `risky` | 固定 1 |
-| `banned` | 固定 0,不参与调度 |
-
-上游持久 WebSocket 连接池同样受账号当前 `DynamicConcurrencyLimit` 约束,连接复用不会突破账号的有效并发上限。
-
-**调度分惩罚/奖励:**
-
-| 信号 | 影响 |
-| --- | --- |
-| `unauthorized` | `-50`,24h 线性衰减 |
-| `rate_limited` | `-22`,1h 线性衰减 |
-| `timeout` | `-18`,15min 线性衰减 |
-| `server error` | `-12`,15min 线性衰减 |
-| 连续失败 | 每次 `-6`,最多 `-24` |
-| 连续成功 | 每次 `+2`,最多 `+12` |
-| 近期成功率过低 | `<75%` 扣 8,`<50%` 扣 15 |
-| Free 7d 用量 | `≥70%` 扣 8 → `≥100%` 扣 40 |
-| 延迟 EWMA | `≥5s` 扣 4 → `≥20s` 扣 15 |
-
-**冷却与恢复机制:**
-
-- **429**:优先解析上游 `resets_at`,否则按套餐类型推断冷却时间
-- **401**:直接进入 `banned`,6h 冷却,24h 内再触发升至 24h
-- 冷却状态持久化到 PostgreSQL,重启后自动恢复
-- 后台会对 `banned` 账号做周期性低频恢复探测
-
-**调度可观测性:**
-
-- `GET /api/admin/accounts` — 健康层级、调度分、惩罚拆解
-- `GET /api/admin/ops/overview` — 系统运行态与连接池概览
-- `/admin/ops/scheduler` — 前端调度看板
-
-**调度模式**(`scheduler_mode`,通过管理后台设置):
-
-| 模式 | 行为 |
+| CODEX_PORT | HTTP 端口,默认 8080 |
+| BIND_HOST | 监听地址,例如 127.0.0.1 或 0.0.0.0 |
+| ADMIN_SECRET | 管理后台登录密钥 |
+| DATABASE_DRIVER | postgres 或 sqlite |
+| DATABASE_PATH | DATABASE_DRIVER=sqlite 时的数据库路径 |
+| DATABASE_HOST / DATABASE_PORT | PostgreSQL 连接地址 |
+| DATABASE_USER / DATABASE_PASSWORD / DATABASE_NAME | PostgreSQL 凭据和数据库名称 |
+| CACHE_DRIVER | redis 或 memory |
+| REDIS_ADDR | Redis 地址或 URL |
+| TZ | IANA 时区,例如 Asia/Shanghai |
+
+调度模式、请求限制和计费选项等业务设置保存在数据库中,可从管理后台修改。完整配置参考:[docs/CONFIGURATION.md](docs/CONFIGURATION.md)
+
+## API 与管理后台
+
+| 接口 | 说明 |
| --- | --- |
-| `round_robin`(默认) | 按健康层级轮询可用账号,权重按调度分排序 |
-| `remaining_quota` | 优先使用用量较低的账号;用量相同时轮询 |
-| `fill_first` | 持续集中使用剩余额度最少的账号,耗尽或限流后再切换到下一个(A → B → C) |
-
-**信用账号**(单账号标记):
-
-对采用信用计费而非 Free/Pro 用量计费的账号,可标记为信用账号以跳过用量窗口惩罚:
-
-| 字段 | 类型 | 作用 |
-| --- | --- | --- |
-| `credit_enabled` | bool | 标记账号为信用计费模式 |
-| `credit_skip_usage_window` | bool | 开启后跳过 7 天/5 小时用量窗口惩罚 |
-
-**窗口化 USD 费用**:账号列表展示每个账号在两个时间窗口内的累计计费金额——过去 5 小时和过去 7 天,窗口对齐各账号的用量重置边界。这反映的是实际扣费金额而非估算的 Token 费用。
-
----
-
-## 目录结构
-
-```text
-codex2api/
-├─ main.go # 程序入口
-├─ Dockerfile # 多阶段镜像构建
-├─ docker-compose.yml # 镜像部署模板
-├─ docker-compose.local.yml # 本地源码构建模板
-├─ .env.example # 环境变量示例
-├─ admin/ # 管理后台 API
-├─ auth/ # 账号池、调度与 token 管理
-├─ cache/ # Redis 缓存封装
-├─ config/ # 环境变量加载
-├─ database/ # 数据库访问层
-├─ proxy/ # 对外代理、转发与限流
-└─ frontend/ # React + Vite 管理后台
- ├─ src/pages/ # Dashboard / Accounts / API Keys / Proxies / Images / Prompt Filter / Ops / Usage / Settings / Docs
- ├─ src/components/ # UI 组件
- ├─ src/locales/ # 国际化语言文件 (zh/en)
- └─ vite.config.js # Vite 配置
-```
-
-
----
-
-## 常见注意事项
-
-- `docker-compose.yml` 拉取 GHCR 镜像用于部署;`docker-compose.local.yml` 用 `build: .` 做本地构建
-- 前端基路径固定为 `/admin/`,本地开发和生产部署一致
-- 本地手动构建 Go 二进制前需先执行 `frontend/` 的 `npm run build`
-- `.env` 只负责端口、数据库、Redis 等物理层配置;业务参数在管理台数据库里维护
-- API Key 以数据库为准,在管理台中配置
-
----
-
-## 交流群
-
-- QQ 交流群:[点击链接加入群聊【codex2api】](https://qun.qq.com/universal-share/share?ac=1&authKey=6vwawW4MeqdACT7PajnHlf2lLkjfuNXEMSos67l9FBiAJ8t%2BKeaXJXB0dgsnhFa1&busi_data=eyJncm91cENvZGUiOiI4MTY3Mzk4NDIiLCJ0b2tlbiI6ImU1YW1KR3dNaXZoUXZDUWpYTWVncmdmMXhQV1RwQ21tbEhkdjB5VW45aWVPSjhFM2grMkRHNGdhWnhEU29oS08iLCJ1aW4iOiIxMTYzNDc2OTQ5In0%3D&data=adSomD6r40Al25rBr8PocFCKumQR5oxi1kq5jXjXxeJ49Z5cj4QLzbNf6vfIQKWMORrJntrZtcoyQuHg2ksUeA&svctype=4&tempid=h5_group_info)(群号:816739842)
-- Telegram 群组:[加入 Telegram 群组](https://t.me/+9hJAA3ZWQxxmMzE5)
-
-欢迎加群交流部署、使用与二次开发相关问题。
-
----
-
-## 免责声明与开源协议
-
-- 本项目仅供学习、研究与技术交流使用。
-- 本项目采用 `MIT License` 开源协议。
-- 项目不对任何直接或间接使用后果提供担保;生产环境使用风险由使用者自行承担。
+| POST /v1/chat/completions | OpenAI 兼容 Chat Completions |
+| POST /v1/responses | Responses API |
+| POST /v1/messages | Anthropic Messages API |
+| POST /v1/images/generations | 图片生成 |
+| GET /v1/models | 可用模型列表 |
+| GET /health | 健康检查 |
----
+主要管理页面包括 /admin/accounts、/admin/api-keys、/admin/usage、/admin/channel-monitors、/admin/settings 和 /admin/ops。API Key 和管理密钥都在管理后台配置。
-## Star History
+费用统计使用模型价格表和[自定义维护内容](#自定义维护内容)中的倍率状态。倍率探查失败或没有可用倍率时,回退到官方模型价格。
-
-