Skip to content
Merged
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
32 changes: 32 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,38 @@ MAX_FILES_PER_REVIEW=50
# Per-request timeout (ms) for every AI provider call. A hung/slow model call
# is aborted at this deadline and the review fails visibly instead of stalling.
AI_REQUEST_TIMEOUT_MS=60000

# ─── Backup AI provider / failover (optional; off unless BACKUP_AI_PROVIDER set) ───
# When the primary provider fails transiently (timeout, 5xx, 429, network), the
# review falls over to this backup so a review is still posted. Peer-quality
# backup recommended. Does NOT fail over on 401/403 (surfaces misconfiguration).
# BACKUP_AI_PROVIDER=anthropic # "anthropic" | "openai" | "openai-compatible"
# Backup creds REUSE the matching primary vars unless a BACKUP_* override is set:
# BACKUP_ANTHROPIC_API_KEY=sk-ant-... # else reuses ANTHROPIC_API_KEY
# BACKUP_ANTHROPIC_MODEL=claude-opus-4-8 # else reuses ANTHROPIC_MODEL
# BACKUP_ANTHROPIC_BASE_URL= # else reuses ANTHROPIC_BASE_URL
# BACKUP_OPENAI_API_KEY= # else reuses OPENAI_API_KEY
# BACKUP_OPENAI_MODEL= # else reuses OPENAI_MODEL
# BACKUP_OPENAI_BASE_URL= # else reuses OPENAI_BASE_URL
# BACKUP_LOCAL_AI_BASE_URL= # else reuses LOCAL_AI_BASE_URL
# BACKUP_LOCAL_AI_MODEL= # else reuses LOCAL_AI_MODEL
# BACKUP_LOCAL_AI_API_KEY= # else reuses LOCAL_AI_API_KEY
# BACKUP_LOCAL_AI_JSON_MODE= # else reuses LOCAL_AI_JSON_MODE
#
# Short deadline given to the PRIMARY when a backup is configured, so a slow-hang
# fails over quickly (clamped to <= AI_REQUEST_TIMEOUT_MS). Default 20000. Set
# this above your primary's observed p95 `review` latency — too low and a
# healthy-but-slow review will routinely time out and fail over, roughly
# doubling latency and cost for that review.
# PRIMARY_AI_TIMEOUT_MS=20000
# Best-effort circuit breaker: after roughly N consecutive failed primary AI
# *calls* it routes straight to the backup for a cooldown, sparing the
# primary's stall during a clear outage. It counts individual provider calls
# (a review makes several, some concurrent), so it's a cost/latency guard, not
# a precise per-review guarantee.
# BACKUP_CIRCUIT_THRESHOLD=3
# BACKUP_CIRCUIT_COOLDOWN_MS=60000

# Comma-separated glob patterns to skip
IGNORED_PATTERNS=

Expand Down
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,37 @@ GitHub webhook
minified assets (`*.min.js`, `*.min.css`), sourcemaps (`*.map`), build output
(`dist/**`, `build/**`, `.next/**`).

### Backup provider / failover

Off by default. Set `BACKUP_AI_PROVIDER` (`anthropic`, `openai`, or
`openai-compatible`) to enable a second provider that the review falls over to
when the primary fails *transiently* (timeout, 5xx, 429, network) — it does
**not** fail over on 401/403, since those indicate misconfiguration rather
than an outage. Backup credentials reuse the matching primary vars
(`ANTHROPIC_*`, `OPENAI_*`, `LOCAL_AI_*`) unless a `BACKUP_*` override is set.
When a backup is configured, the primary is given a short deadline
(`PRIMARY_AI_TIMEOUT_MS`, default 20000ms) so a slow-hang fails over quickly
instead of eating the full `AI_REQUEST_TIMEOUT_MS`. Set it above your
primary's observed p95 `review` latency — too low and a healthy-but-slow
review will routinely time out and fail over, roughly doubling latency and
cost for that review. A best-effort circuit breaker
(`BACKUP_CIRCUIT_THRESHOLD` / `BACKUP_CIRCUIT_COOLDOWN_MS`) routes straight to
the backup for a cooldown after roughly N consecutive failed primary AI
*calls*, sparing the primary's stall during a clear outage. It counts
individual provider calls (a review makes several, some concurrent, and a
succeeding one can reset the counter), so it's a cost/latency guard, not a
precise per-review guarantee.

| Variable | Required | Default | Description |
|---|---|---|---|
| `BACKUP_AI_PROVIDER` | No | | `anthropic`, `openai`, or `openai-compatible`. Unset = failover disabled. |
| `PRIMARY_AI_TIMEOUT_MS` | No | `20000` | Deadline given to the primary before failing over (clamped to `AI_REQUEST_TIMEOUT_MS`). |
| `BACKUP_CIRCUIT_THRESHOLD` | No | `3` | Roughly this many consecutive failed primary AI *calls* before the circuit breaker skips it (best-effort, not a precise per-review count). |
| `BACKUP_CIRCUIT_COOLDOWN_MS` | No | `60000` | How long the circuit breaker stays open before retrying the primary. |

See `.env.example` for the full list of `BACKUP_ANTHROPIC_*` / `BACKUP_OPENAI_*` /
`BACKUP_LOCAL_AI_*` override vars.

## Using local models (Ollama, LM Studio, vLLM, llama.cpp, LocalAI)

DiffSentry can talk to any server that exposes an **OpenAI-compatible
Expand Down
Loading
Loading