FastAPI proxy service that wraps CodeBuddy's official API into an OpenAI-compatible interface (/v1/chat/completions). Includes a Web admin UI, OAuth2-based credential auto-acquisition, and hot-reloadable config.
uv sync --extra dev # install deps
python web.py # run dev server (Hypercorn ASGI)
./run_docker_in_server.sh deploy # build + run via Docker (tagged by git hash)Entry point is web.py. No separate dev/watch mode — just restart.
ruff check . # lint
mypy src/ # type check
pytest # tests (no test files yet)- Single source of truth:
config/config.yaml(auto-created from the checked-inconfig.example.yamlon first run). Legacyconfig/config.jsonis auto-migrated once. No.env/ env vars. server.passwordis required — service returns 500 if unset- All log params (level/rotation/retention/compression) live under
logging.*and are read live bysrc/core/logging.py; changing them via the UI rebuilds the loguru handlers - Default API endpoint is
codebuddy.cn— configurable, used dynamically everywhere - Credentials stored as JSON files in
.codebuddy_creds/; token manager auto-rotates them - Settings changes via Web UI persist to
config/config.yaml(full overwrite) and hot-reload without restart - The Settings API still speaks flat
CODEBUDDY_*keys for frontend compatibility;src/core/config.pytranslates flat ↔ nested internally
web.py → FastAPI app, lifespan, mounts all routers
config.py → Config loading/hot-reload/save (singleton module, auto-loads on import)
src/
auth.py → Bearer token auth (password == CODEBUDDY_PASSWORD)
http_client.py → HTTP client pool + lifecycle manager (imports lifecycle_manager for web.py)
sse_utils.py → SSE parsing, formatting, OpenAI compatibility converter
stream_handler.py → SSE connection manager, response aggregator, stream/non-stream service
request_processor.py → Request validation + payload prep, credential selection
codebuddy_router.py → Route definitions only (~240 lines, delegates to other modules)
codebuddy_api_client.py → CodeBuddy header generation, message conversion
codebuddy_token_manager.py → Credential loading, rotation, state persistence
codebuddy_auth_router.py → OAuth2 PKCE flow for auto-acquiring CodeBuddy tokens
keyword_replacer.py → Replaces competitor names in responses
frontend_router.py → Serves frontend/admin.html
settings_router.py → GET/POST /api/settings, /api/stats
usage_stats_manager.py → Singleton, in-memory thread-safe counters
models.py → Pydantic request/response models
frontend/admin.html → Single-file Web UI
- No requirements.txt — deps are in
pyproject.toml+uv.lock. Useuv sync, not pip src/core/config.py↔src/core/logging.pyhave a circular import: config callsapply_log_levelat end of its import; logging reads config lazily inside functions. Don't add top-level config imports to logging.py- CodeBuddy's API is stream-only; non-stream requests are assembled by buffering SSE chunks in
stream_handler.py keyword_replacer.pymutates responses to swap competitor names — be aware when debugging response content issues- Endpoint URLs (
Host,X-Domain) are extracted dynamically from thecodebuddy.api_endpointconfig authenticateis defined once insrc/auth.py— other modules import from there
- Deploy via
run_docker_in_server.sh(subcommands: build/deploy/start/images/rm-image/help). No docker-compose.deploy=build+ start + cleanup;buildonly builds the image. - Image is tagged by the git commit hash prefix (
IMAGE_TAG_LENGTH, default 8); the full hash is baked in as theorg.opencontainers.image.revisionlabel via theCODEBUDDY2API_GIT_COMMIT_HASHbuild-arg. - Volume mounts (bind, under
DATA_ROOT, default$REPO_ROOT/data):config/→/app/config,creds/→/app/.codebuddy_creds,logs/→/app/logs. - On first deploy the script copies
config.example.yamlintoDATA_ROOT/config/config.yamland rewritesserver.hostto0.0.0.0(setSKIP_CONFIG_ADAPT=1to skip).creds_dirstays.codebuddy_creds, which resolves to the mounted/app/.codebuddy_creds. deploywaits for/healthbefore cleaning old images (IMAGE_RETENTION_COUNT, default 5).
| Route | Auth | Purpose |
|---|---|---|
POST /codebuddy/v1/chat/completions |
Bearer (password) | Core chat proxy |
GET /codebuddy/v1/models |
Bearer | List configured models |
GET /codebuddy/v1/credentials |
Bearer | List loaded credentials |
POST /codebuddy/v1/credentials/delete |
Bearer | Delete credential by index |
GET /codebuddy/auth/start |
None | Begin OAuth2 flow |
GET /codebuddy/auth/poll |
None | Poll auth status |
GET /api/settings |
Bearer | Read config |
POST /api/settings |
Bearer | Update + persist + hot-reload config |
GET /api/stats |
Bearer | Usage counters |
GET /health |
None | Health check |