From 06cbb25a546b1b97ddbc008dbc80c6a3172384aa Mon Sep 17 00:00:00 2001 From: Jay Date: Wed, 30 Sep 2026 19:42:01 +0800 Subject: [PATCH] docs: update maintained README and release notes --- .github/workflows/release.yml | 41 +++ README.md | 583 +++++-------------------------- README.zh-CN.md | 630 +++++----------------------------- 3 files changed, 205 insertions(+), 1049 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c4c9ce92b..5b5a59572 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,6 +42,7 @@ jobs: uses: actions/checkout@v5 with: ref: ${{ inputs.source_ref || inputs.release_tag || github.ref }} + fetch-depth: 0 - name: Set up Node.js uses: actions/setup-node@v5 @@ -111,10 +112,50 @@ jobs: sha256sum * > SHA256SUMS.txt ) + - name: Prepare release notes + shell: bash + run: | + set -euo pipefail + + notes_file="$RUNNER_TEMP/codex2api-release-notes.md" + version="$VERSION" + previous_tag="$(git tag --sort=-version:refname \ + | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \ + | grep -Fxv "$version" \ + | head -n 1 || true)" + + awk ' + /^## Custom maintenance$/ { in_section=1 } + in_section && /^## / && $0 != "## Custom maintenance" { exit } + in_section { print } + ' README.md > "$notes_file" + + printf '\n---\n\n' >> "$notes_file" + awk ' + /^## 自定义维护内容$/ { in_section=1 } + in_section && /^## / && $0 != "## 自定义维护内容" { exit } + in_section { print } + ' README.zh-CN.md >> "$notes_file" + + printf '\n## Custom changes in this release\n\n' >> "$notes_file" + custom_commits="" + if [[ -n "$previous_tag" ]]; then + custom_commits="$(git log --first-parent --format='- %s' \ + "$previous_tag..$SOURCE_REF" -- \ + ':!CHANGELOG.md' ':!docs/**' ':!.github/**' \ + | grep -Ev '^- (Merge pull request|chore: sync upstream release|ci:)' || true)" + fi + if [[ -n "$custom_commits" ]]; then + printf '%s\n' "$custom_commits" >> "$notes_file" + else + printf '%s\n' '- No additional custom code changes were recorded for this release.' >> "$notes_file" + fi + - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: tag_name: ${{ inputs.release_tag || github.ref_name }} + body_path: ${{ runner.temp }}/codex2api-release-notes.md generate_release_notes: true files: | dist/*.tar.gz diff --git a/README.md b/README.md index 194867b66..fedbbb642 100644 --- a/README.md +++ b/README.md @@ -17,562 +17,145 @@ Docker

-**Turn a Codex account pool into an observable, schedulable, operations-ready OpenAI / Anthropic compatible gateway.** Codex2API is not a thin forwarding proxy. It is a long-running Codex access hub: it exposes `/v1/chat/completions`, `/v1/responses`, `/v1/messages`, Images, Videos (Grok Imagine), and Models endpoints while managing Refresh Token / Access Token accounts, health scoring, dynamic concurrency, rate-limit recovery, usage tracking, and admin operations behind the scenes. +**Codex2API turns a Codex account pool into an observable, schedulable OpenAI / Anthropic compatible gateway.** It provides Chat Completions, Responses, Messages, Images, Models and administration endpoints while handling account selection, token refresh, health state, rate-limit recovery and usage records. -Run it as a full **PostgreSQL + Redis** production stack or as a single-container **SQLite + in-memory cache** deployment. Point Codex CLI, Claude Code, the OpenAI SDK, or any compatible client at one Base URL, then manage accounts, proxies, API keys, prompt filtering, image workflows, and runtime settings from the built-in dashboard. +This repository is a maintained fork with additional billing, upstream monitoring and responsive usage features. Upstream functionality remains available unless it conflicts with the maintained custom behavior described below. - - - - - - - -
One compatible gatewayOpenAI-style Chat Completions / Responses / Images, Anthropic Messages, prefixless compatibility routes, and native Codex Responses forwarding are all exposed through one service.
Account-pool schedulerSelection 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 consoleThe 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 shapesUse 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 observabilityPer-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 checkCompare 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.
+## Custom maintenance ---- +- **Upstream multiplier discovery:** Accounts connected to Sub2API can opt into multiplier discovery. Manual probing and periodic probing are supported, with strict response validation and the last valid value retained for temporary probe failures. +- **Multiplier-aware billing:** Normal accounts use the official model price. When a valid upstream multiplier is available, user billing and upstream cost estimation keep the official base price and apply the multiplier separately. The account, API key and usage views expose the multiplier and the related cost details. +- **Channel health monitoring:** Channel availability, probe status, response time and recent failures can be checked from the administration console without waiting for a user request. +- **Mobile usage details:** Usage cost details, tooltips and account information remain readable and usable on small screens as well as desktop screens. +- **Pricing coverage:** The maintained pricing mapping covers current upstream model aliases, standard and long-context boundaries, and the fallback path used when a model is not returned by an upstream pricing probe. -## Live Demo +## Quick start -- Demo URL: [https://codex2api-latest-vu8j.onrender.com](https://codex2api-latest-vu8j.onrender.com) -- Demo password: `codex2api` +For the full deployment guide, see [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md). -> The demo is only for trying the admin dashboard and basic UI flows. Do not upload real Refresh Tokens, Access Tokens, API keys, or any other sensitive data. +### Deployment modes ---- - -## Screenshots - -> Screenshots use demo data. The actual dashboard depends on your account pool, request logs, and runtime environment. - -![CodexProxy Dashboard](docs/screenshots/dashboard.png) - -
-More admin dashboard screenshots - -| Accounts | Dashboard Trends | -| --- | --- | -| ![Accounts](docs/screenshots/accounts.png) | ![Dashboard Trends](docs/screenshots/dashboard-trends.png) | - -| Image Studio | Prompt Filter | -| --- | --- | -| ![Image Studio](docs/screenshots/image-studio.png) | ![Prompt Filter](docs/screenshots/prompt-filter.png) | - -| Operations | Usage | -| --- | --- | -| ![Operations](docs/screenshots/operations.png) | ![Usage](docs/screenshots/usage.png) | - -| Usage Guide | API Reference | -| --- | --- | -| ![Usage Guide](docs/screenshots/guide.png) | ![API Reference](docs/screenshots/api-reference.png) | - -
- ---- - - -## Contents - -- [Live Demo](#live-demo) -- [Screenshots](#screenshots) -- [Sponsors](#sponsors) -- [Quick Start](#quick-start) -- [Documentation](#documentation) -- [Upgrade and Local Development](#upgrade-and-local-development) -- [Configuration](#configuration) -- [Public API](#public-api) - - [Token Upload and Account Management](#token-upload-and-account-management) -- [Admin Dashboard](#admin-dashboard) -- [Core Capabilities](#core-capabilities) -- [Project Structure](#project-structure) -- [Notes](#notes) -- [Community](#community) -- [Disclaimer and License](#disclaimer-and-license) -- [Star History](#star-history) -- [Links](#links) - ---- - -## Quick Start - -> For detailed deployment instructions, see [DEPLOYMENT.md](docs/DEPLOYMENT.md). - -### Deployment Modes - -| Mode | File | Use Case | +| Mode | File | Use case | | --- | --- | --- | -| Docker image deployment | `docker-compose.yml` | Recommended for servers and test environments using the prebuilt image | -| Local source container build | `docker-compose.local.yml` | Full container verification after local source changes | -| SQLite lightweight deployment | `docker-compose.sqlite.yml` | Single-node deployment without PostgreSQL or Redis | -| SQLite local source build | `docker-compose.sqlite.local.yml` | Local source verification for the lightweight SQLite mode | -| Local development | `go run .` + `npm run dev` | Backend and frontend development | +| Docker image | 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 - - - - - - Star History Chart - - +## Documentation ---- +- [Deployment](docs/DEPLOYMENT.md) +- [Usage](docs/USAGE.md) +- [API reference](docs/API.md) +- [Configuration](docs/CONFIGURATION.md) +- [Architecture](docs/ARCHITECTURE.md) +- [Troubleshooting](docs/TROUBLESHOOTING.md) +- [中文说明](README.zh-CN.md) -## Links +## Disclaimer and license -- [LINUX DO](https://linux.do/) +This project is provided for learning, research and technical discussion. Use it only where you have the right to access the upstream services and accept responsibility for your deployment. The project is released under the MIT License without warranty. diff --git a/README.zh-CN.md b/README.zh-CN.md index 9840ce31d..c5046bc7c 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -17,613 +17,145 @@ Docker

-**把 Codex 账号池变成可观测、可调度、可运维的 OpenAI / Anthropic 兼容网关。** Codex2API 不是一个薄转发层,而是一套面向长期运行的 Codex 接入中枢:对外提供 `/v1/chat/completions`、`/v1/responses`、`/v1/messages`、Images 和 Models 等接口,对内维护 Refresh Token / Access Token 账号池、健康度评分、动态并发、限流恢复、用量统计和后台运维。 +**Codex2API 把 Codex 账号池变成可观测、可调度的 OpenAI / Anthropic 兼容网关。** 它提供 Chat Completions、Responses、Messages、Images、Models 和管理接口,并负责账号调度、Token 刷新、健康状态、限流恢复和用量记录。 -它可以跑在完整的 **PostgreSQL + Redis** 生产形态,也可以用 **SQLite + 内存缓存** 单容器轻量部署。你可以把它接到 Codex CLI、Claude Code、OpenAI SDK 或任何兼容客户端上,用一个统一 Base URL 管理多账号、代理池、API Key、Prompt 检查、生图工作台和运行时配置。 +本仓库是在上游项目基础上的持续维护版本,增加了计费、上游状态监控和移动端用量展示能力。上游功能继续保留,除非与下面列出的自定义行为发生冲突。 - - - - - - -
统一兼容入口同时覆盖 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 过滤,以及含请求日志与趋势图表的用量仪表盘。
+## 自定义维护内容 ---- - -## 在线 Demo - -- Demo 地址:[https://codex2api-latest-vu8j.onrender.com](https://codex2api-latest-vu8j.onrender.com) -- Demo 密码:`codex2api` - -> Demo 环境仅用于体验管理后台界面和基础功能,请勿上传真实 Refresh Token、Access Token、API Key 或其他敏感信息。 - ---- - -## 界面预览 - -> 以下截图使用演示数据,实际页面会随账号池、请求日志和运行环境变化。 - -![CodexProxy 仪表盘](docs/screenshots/dashboard.png) - -
-查看更多后台界面 - -| 账号管理 | 仪表盘趋势 | -| --- | --- | -| ![账号管理](docs/screenshots/accounts.png) | ![仪表盘趋势](docs/screenshots/dashboard-trends.png) | - -| 生图工作台 | Prompt 检查 | -| --- | --- | -| ![生图工作台](docs/screenshots/image-studio.png) | ![Prompt 检查](docs/screenshots/prompt-filter.png) | - -| 系统运维 | 使用统计 | -| --- | --- | -| ![系统运维](docs/screenshots/operations.png) | ![使用统计](docs/screenshots/usage.png) | - -| 使用文档 | API 文档 | -| --- | --- | -| ![使用文档](docs/screenshots/guide.png) | ![API 文档](docs/screenshots/api-reference.png) | - -
- ---- - - - -## 目录 - -- [在线 Demo](#在线-demo) -- [界面预览](#界面预览) -- [赞助商](#赞助商) -- [快速部署](#快速部署) - - [一键交互部署 (推荐)](#一键交互部署-推荐) -- [完整文档](#完整文档) -- [升级与本地开发](#升级与本地开发) -- [环境配置](#环境配置) -- [对外接口](#对外接口) - - [Token 上传与账号管理](#token-上传与账号管理) -- [管理后台](#管理后台) -- [核心能力](#核心能力) -- [目录结构](#目录结构) -- [常见注意事项](#常见注意事项) -- [交流群](#交流群) -- [免责声明](#免责声明与开源协议) -- [Star History](#star-history) -- [友情链接](#友情链接) - ---- +- **上游倍率探查:** 接入 Sub2API 的账号可以选择开启倍率探查,支持手动探查和定时探查,并对响应协议进行严格校验。临时探查失败时保留最后一次有效倍率。 +- **倍率计费:** 普通账号按照官方模型价格计算。探查到有效上游倍率后,用户费用和上游成本估算以官方基础价格为依据,再单独应用倍率。账号、API Key 和使用统计页面会显示倍率及对应费用信息。 +- **渠道健康监控:** 管理后台可以主动检查渠道可用性、探查状态、响应时间和近期失败记录,不需要等到用户请求发生后才发现问题。 +- **移动端用量展示:** 费用明细、提示信息和账号信息在小屏幕上保持清晰可读,移动端点击提示也能正常使用。 +- **模型价格覆盖:** 维护版本补齐当前上游模型别名、标准价格、长上下文边界,以及上游价格探查不可用时的回退路径。 ## 快速部署 -> 详细部署指南请参考:[DEPLOYMENT.md](docs/DEPLOYMENT.md) - -### 一键交互部署 (推荐) - -`deploy.sh` 提供 6 步交互式向导,依次询问 **端口 / 监听范围 / 数据库 / 密钥 / 构建方式 / 确认**,会先尝试拉取最新代码,再自动生成 `.env` 并拉起容器。 - -如果当前目录已有 `.env`,脚本会读取其中的端口、监听地址、数据库、Redis、管理密钥和 API 密钥作为默认值,后续重跑脚本时可直接回车复用原配置。 - -脚本会先检查当前系统是首次部署还是已有部署;如果发现已有 `.env` 或 compose 服务,会读取现有配置作为默认值,再进入完整部署向导。 - -**场景 1:尚未克隆仓库(一行远程拉起)** - -```bash -bash <(curl -sSL https://raw.githubusercontent.com/james-6-23/codex2api/main/deploy.sh) -``` - -脚本会自动检测当前目录是否是 `codex2api` 仓库,若不是则克隆到 `./codex2api`,进入目录后再执行部署。 - -**场景 2:已经 `git clone` 到本地** - -```bash -git clone https://github.com/james-6-23/codex2api.git -cd codex2api -bash deploy.sh -``` - -**监听范围选项** - -| 选项 | 绑定地址 | 适用场景 | -| --- | --- | --- | -| 1) 仅本机访问 | `127.0.0.1` | 服务放在 nginx / Caddy 等反向代理后端,外网无法直接访问端口 | -| 2) 全部网络 (默认) | `0.0.0.0` | 直接通过服务器 IP 对外暴露,部署完成后会展示本机 / 内网 / 公网地址 | +完整部署说明请参考:[docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) -绑定地址会写入 `.env` 的 `BIND_HOST`,后续可手动修改后 `docker compose up -d` 重启生效。 - -**可选环境变量**(用于自定义自举行为) - -| 变量 | 默认 | 说明 | -| --- | --- | --- | -| `CODEX2API_REPO_URL` | `https://github.com/james-6-23/codex2api.git` | 克隆使用的仓库地址 | -| `CODEX2API_REPO_BRANCH` | `main` | 克隆使用的分支 | -| `CODEX2API_DIR_NAME` | `codex2api` | 克隆到本地的目录名 | -| `CODEX2API_SKIP_GIT_PULL` | 空 | 设为 `1` 或 `true` 时跳过部署前自动拉取最新代码 | - -### 部署模式总览 +### 部署模式 | 模式 | 文件 | 适用场景 | | --- | --- | --- | -| Docker 镜像部署 | `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` | 前后端联调与调试 | - -### 部署命令速查 +| Docker 镜像 | 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 +费用统计使用模型价格表和[自定义维护内容](#自定义维护内容)中的倍率状态。倍率探查失败或没有可用倍率时,回退到官方模型价格。 - - - - - Star History Chart - - +## 文档 ---- +- [部署说明](docs/DEPLOYMENT.md) +- [使用指南](docs/USAGE.md) +- [API 参考](docs/API.md) +- [配置说明](docs/CONFIGURATION.md) +- [架构说明](docs/ARCHITECTURE.md) +- [故障排查](docs/TROUBLESHOOTING.md) +- [English README](README.md) -## 友情链接 +## 免责声明与协议 -- [LINUX DO](https://linux.do/) +本项目用于学习、研究和技术交流。请只在你有权访问的上游服务中使用,并自行承担部署和使用责任。本项目采用 MIT 协议发布,不提供任何明示或默示担保。