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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ Thumbs.db
*.env.*
!.env.example

# Upstream API keys are provided through the config volume
config/codebuddy_api_keys.txt

# Log files
*.log
logs/
217 changes: 196 additions & 21 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,47 +1,222 @@
# ===============================================================
# CodeBuddy2API - 环境变量示例文件
# CodeBuddy2API - Environment variable example
#
# 使用前,请将此文件复制为 .env 并填写必要的值
# Copy this file to .env and provide the required values before use.
# ===============================================================

# -----------------
# 服务端配置
# Server configuration
# -----------------

# (必需) API服务的访问密码,客户端连接时需要在Authorization头中提供此密码
CODEBUDDY_PASSWORD=
# (Required) Password clients must provide in the Authorization header.
# This password authenticates clients/9Router only and is never used as an upstream CodeBuddy API key.
CODEBUDDY_PASSWORD=relay_master_secret

# (可选) 服务监听的主机地址
# 默认值: 127.0.0.1
# (Optional) Service bind address.
# Default: 127.0.0.1
CODEBUDDY_HOST=127.0.0.1

# (可选) 服务监听的端口
# 默认值: 8001
# (Optional) Service port.
# Default: 8001
CODEBUDDY_PORT=8001


# -----------------
# CodeBuddy API 配置
# Adapter selection (spec §1)
# -----------------

# (可选) CodeBuddy官方API的端点地址
# 一般无需修改
# (Optional) Which request pipeline handles /v1/chat/completions.
# v2 -> the isolated CodeBuddyAdapterV2 (default): strict model resolver,
# deterministic Anthropic/OpenAI message normalization, streaming
# tool-call state machine, granular timeouts, and cancellation.
# legacy -> the original monolithic handler, kept as a fallback.
# Default: v2
CODEBUDDY_ADAPTER_VERSION=v2


# -----------------
# CodeBuddy API configuration
# -----------------

# (Optional) Official CodeBuddy API endpoint.
# This is correct for CodeBuddy Global and normally does not need to be changed.
CODEBUDDY_API_ENDPOINT=https://www.codebuddy.ai

# (可选) 存放CodeBuddy认证凭证 (JSON文件) 的目录
# 默认值: .codebuddy_creds
# (Optional) Upstream request profile: web or cli.
# web -> browser-like User-Agent, sends both Authorization and X-Api-Key,
# and omits CLI/IDE identity headers. Reduces false-positive moderation.
# cli -> preserves the legacy CLI/IDE headers for backward compatibility.
# Default: web
CODEBUDDY_REQUEST_PROFILE=web

# (Optional) Sanitize long or agent-style system prompts (Claude Code, Cursor,
# Cline, etc.) that tend to trigger CodeBuddy false-positive moderation.
# Only the system message is replaced; user/assistant/tool messages are untouched.
# Default: true
CODEBUDDY_SANITIZE_AGENT_PROMPT=true

# (Optional) Maximum system prompt length (characters). System prompts longer
# than this are replaced with a short neutral instruction.
# Default: 2000
CODEBUDDY_MAX_SYSTEM_PROMPT_LENGTH=2000

# (Optional) Fallback model used when the client sends an unknown model label
# (e.g. a UI display name). Must be a model CodeBuddy actually supports.
# Default: auto-chat
CODEBUDDY_DEFAULT_MODEL=auto-chat

# (Optional) How an unknown model label (neither a known upstream model ID nor a
# configured alias) is handled. An unknown model is NEVER silently rewritten.
# passthrough (default) -> forward the requested model verbatim; CodeBuddy
# accepts or rejects it.
# reject -> return HTTP 400 (code=unknown_model) locally.
# default -> fall back to CODEBUDDY_DEFAULT_MODEL.
CODEBUDDY_UNKNOWN_MODEL_POLICY=passthrough

# (Optional) Model alias map for UI display labels that are not valid upstream
# model IDs. Comma-separated alias=upstream pairs, matched case-insensitively.
# Example: Claude Opus 4.7=claude-4.0,GPT-5 (UI)=gpt-5
# Only allowlisted upstream fields (model, messages, stream, tools, tool_choice)
# are forwarded to CodeBuddy; other OpenAI fields are ignored.
CODEBUDDY_MODEL_ALIASES=

# (Optional) Directory containing CodeBuddy credential JSON files.
# Default: .codebuddy_creds
CODEBUDDY_CREDS_DIR=.codebuddy_creds

# (Optional) Upstream authentication mode: auto, api_key_file, credentials.
# auto prefers TXT API keys and falls back to the legacy credential system when none are available.
CODEBUDDY_AUTH_MODE=auto

# (Optional) TXT file containing one upstream CodeBuddy API key per line.
CODEBUDDY_API_KEYS_FILE=./config/codebuddy_api_keys.txt

# (Optional) API key rotation strategy. round_robin is currently supported.
CODEBUDDY_API_KEY_ROTATION=round_robin

# (Optional) Automatic API key file reload interval in seconds; 0 disables periodic reloads.
CODEBUDDY_API_KEY_RELOAD_INTERVAL=5

# (Optional) Key cooldown period in seconds after a 403 or 429 response.
CODEBUDDY_API_KEY_COOLDOWN_SECONDS=300

# (Optional) Client authentication mode: relay, passthrough, hybrid.
# relay preserves legacy behavior; passthrough uses the client Bearer token as the upstream key for that request.
CODEBUDDY_CLIENT_AUTH_MODE=relay

# (Optional) Dashboard and management endpoint password; empty falls back to CODEBUDDY_PASSWORD.
CODEBUDDY_ADMIN_PASSWORD=

# (Optional) Upstream API key header: x-api-key, bearer, both.
# bearer is the currently verified default mode.
CODEBUDDY_UPSTREAM_API_KEY_HEADER=bearer


# -----------------
# 高级配置
# Advanced configuration
# -----------------

# (可选) 应用的日志级别
# 可选值: DEBUG, INFO, WARNING, ERROR, CRITICAL
# 默认值: INFO
# (Optional) Application log level.
# Values: DEBUG, INFO, WARNING, ERROR, CRITICAL
# Default: INFO
CODEBUDDY_LOG_LEVEL=INFO

# (可选) 向客户端报告可用的模型列表,用逗号分隔
# 用户可以根据自己的CodeBuddy账号支持的模型进行修改
CODEBUDDY_MODELS=claude-4.0,claude-3.7,gpt-5,gpt-5-mini,gpt-5-nano,o4-mini,gemini-2.5-flash,gemini-2.5-pro,auto-chat

# -----------------
# Adapter V2 timeouts and concurrency (spec §12, §16)
# -----------------
# Each upstream stage has its own timeout so a failure is reported precisely
# (e.g. upstream_first_chunk_timeout) instead of a generic connect timeout.

# (Optional) TCP connection establishment timeout (seconds). Default: 30
CODEBUDDY_CONNECT_TIMEOUT_SECONDS=30

# (Optional) Connection-pool acquisition timeout (seconds). Default: 30
CODEBUDDY_POOL_TIMEOUT_SECONDS=30

# (Optional) Request-body write timeout (seconds). Default: 60
CODEBUDDY_WRITE_TIMEOUT_SECONDS=60

# (Optional) Time to wait for upstream response headers (seconds). Default: 300
CODEBUDDY_HEADERS_TIMEOUT_SECONDS=300

# (Optional) Time to wait for the first SSE chunk after headers (seconds).
# Default: 300
CODEBUDDY_FIRST_CHUNK_TIMEOUT_SECONDS=300

# (Optional) Maximum idle gap between SSE chunks before aborting (seconds).
# Default: 600
CODEBUDDY_STREAM_IDLE_TIMEOUT_SECONDS=600

# (Optional) Maximum concurrent in-flight upstream requests. Default: 20
CODEBUDDY_MAX_CONCURRENT_UPSTREAM_REQUESTS=20

# (Optional) Max time to wait for a concurrency slot before returning
# upstream_queue_timeout (seconds). Default: 60
CODEBUDDY_UPSTREAM_QUEUE_TIMEOUT_SECONDS=60

# (Optional) Large-agentic-request warning thresholds. Exceeding any of these
# only logs large_agentic_request=true; context and tools are NEVER truncated.
# Upstream connection / timeout tuning
# -----------------
# These timeouts are intentionally separate so a slow-but-alive agentic stream
# (many tools, long tool results) is not killed by the same short deadline used
# to open a connection. Do NOT use a single global 15s timeout for agentic
# requests.

# (Optional) Time allowed to open a TCP/TLS connection to CodeBuddy. Default: 30
CODEBUDDY_CONNECT_TIMEOUT_SECONDS=30

# (Optional) Time allowed to wait for a free slot in the connection pool. Default: 30
CODEBUDDY_POOL_TIMEOUT_SECONDS=30

# (Optional) Time allowed to write the request body upstream. Default: 60
CODEBUDDY_WRITE_TIMEOUT_SECONDS=60

# (Optional) Time allowed for upstream to return headers + the first chunk.
# Sized for tool-heavy agentic requests. Default: 180
CODEBUDDY_FIRST_BYTE_TIMEOUT_SECONDS=180

# (Optional) Per-read timeout once the stream is flowing. 0 = unlimited. Default: 0
CODEBUDDY_STREAM_READ_TIMEOUT_SECONDS=0

# (Optional) Connection pool sizing. Defaults: 30 keepalive / 100 max / 60s expiry
CODEBUDDY_MAX_KEEPALIVE_CONNECTIONS=30
CODEBUDDY_MAX_CONNECTIONS=100
CODEBUDDY_KEEPALIVE_EXPIRY_SECONDS=60


# -----------------
# Upstream concurrency limiter
# -----------------
# Bounds how many upstream requests run at once so tool-heavy bursts do not pile
# up sockets/tasks without limit. Requests beyond the limit queue up to the
# queue timeout, then receive HTTP 503 (code=upstream_queue_timeout).

# (Optional) Max simultaneous in-flight upstream requests. Default: 20
CODEBUDDY_MAX_CONCURRENT_UPSTREAM_REQUESTS=20

# (Optional) Max time a request waits for a concurrency slot before 503. Default: 60
CODEBUDDY_UPSTREAM_QUEUE_TIMEOUT_SECONDS=60


# -----------------
# SSE heartbeat
# -----------------
# While waiting for the first upstream chunk (after upstream status is known to
# be 200), a heartbeat comment (": ping") is sent to keep the downstream
# connection alive. Heartbeats never become assistant content and stop once the
# real stream starts or the client disconnects. 0 disables heartbeats.
CODEBUDDY_HEARTBEAT_INTERVAL_SECONDS=15


# -----------------
# Large-request warnings (log only; never truncates the request)
# -----------------
CODEBUDDY_WARN_TOTAL_CONTENT_LENGTH=50000
CODEBUDDY_WARN_MESSAGE_COUNT=40
CODEBUDDY_WARN_TOOL_COUNT=30

# (Optional) Comma-separated model list reported to clients.
# Adjust this list to match the models supported by your CodeBuddy account.
CODEBUDDY_MODELS=claude-4.0,claude-3.7,gpt-5,gpt-5-mini,gpt-5-nano,o4-mini,gemini-2.5-flash,gemini-2.5-pro,auto-chat
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ dmypy.json
# Or, if you have an example file, you can explicitly un-ignore it like this:
# !.codebuddy_creds/credential.example.json

# Never commit upstream API keys. The example file remains tracked.
config/codebuddy_api_keys.txt

# IDE files
.vscode/
.idea/
Expand Down
28 changes: 13 additions & 15 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,37 +1,35 @@
# 使用官方的、轻量级的 Python 镜像作为基础
# Use the official lightweight Python image as the base.
FROM python:3.11-slim

# 设置容器内的工作目录
# Set the container working directory.
WORKDIR /app

# 复制依赖文件
# Copy the dependency file.
COPY requirements.txt .

# 安装依赖
# --no-cache-dir 选项可以减小镜像体积
# Install dependencies. --no-cache-dir reduces the image size.
RUN pip install --no-cache-dir -r requirements.txt

# 将项目的所有文件复制到工作目录中
# Copy the project into the working directory.
COPY . .

# 安装 gosu,一个轻量级的 su/sudo 替代品,用于在脚本中切换用户
# 并在同一层中进行清理以减小镜像体积
# Install gosu, a lightweight su/sudo alternative used to switch users.
# Clean package metadata in the same layer to reduce image size.
RUN apt-get update && \
apt-get install -y gosu && \
rm -rf /var/lib/apt/lists/*

# 复制并设置入口脚本
# Install the container entrypoint.
COPY entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

# 创建一个非root用户来运行应用
# Create a non-root user for the application.
RUN useradd -m -u 1001 appuser

# 声明容器将要监听的端口
# 这个端口应该与您在配置中设置的 CODEBUDDY_PORT 一致
# Document the port exposed by the container.
# This should match the internal CODEBUDDY_PORT configuration.
EXPOSE 8001

# 定义容器启动时要执行的命令
# 使用 Hypercorn 启动,它是一个生产级的 ASGI 服务器
CMD ["hypercorn", "web:app", "--bind", "0.0.0.0:8001"]
# Start the production ASGI server with Hypercorn.
CMD ["hypercorn", "web:app", "--bind", "0.0.0.0:8001"]
Loading