pr-reviewer/app/config.py
Adam Moussa 46cd856fb3
Add pr-reviewer local PR review tool
A single-user local dashboard that pulls open PRs from the
Sea-Haven-Industries org, reviews each with a Fireworks model in the
BLOCK/FIX/NIT/QUESTION format, and posts the review to GitHub as the
token owner. Runs only on localhost; secrets stay in a gitignored .env
and never reach the browser.

Structured as an app/ package plus a static/ frontend so the module
imports and static mount resolve. HTTP uses httpx2 (the runtime lib
starlette's TestClient now prefers), pinned in requirements.txt.

Includes a stdlib-only pytest suite (network mocked, no extra test
deps so CI needs only pytest) with a skip-by-default live Fireworks
test, and CI wired to the org ci-python-app reusable workflow to lint
app and tests and run the mocked suite fully offline. Dependabot covers
pip and github-actions.
2026-07-01 13:48:10 -04:00

60 lines
2.2 KiB
Python

"""Configuration loaded from environment / .env.
Secrets never reach the browser. The frontend talks only to this local
backend; the backend holds the GitHub PAT and Fireworks key.
"""
import os
from functools import lru_cache
from dotenv import load_dotenv
load_dotenv()
class Config:
# --- GitHub ---
# Either provide GITHUB_TOKEN (a PAT) here, or leave it blank to fall
# back to `gh auth token` from your local gh CLI (see github_client.py).
GITHUB_TOKEN: str = os.getenv("GITHUB_TOKEN", "").strip()
GITHUB_ORG: str = os.getenv("GITHUB_ORG", "Sea-Haven-Industries").strip()
# The search filter that defines the review queue.
PR_SEARCH_FILTER: str = os.getenv(
"PR_SEARCH_FILTER",
"is:pr state:open archived:false sort:updated-desc org:Sea-Haven-Industries",
).strip()
# Cap how many PRs we pull per refresh.
MAX_PRS: int = int(os.getenv("MAX_PRS", "30"))
# Skip diffs larger than this many bytes (keeps token cost sane).
MAX_DIFF_BYTES: int = int(os.getenv("MAX_DIFF_BYTES", "120000"))
# --- Fireworks (OpenAI-compatible endpoint) ---
FIREWORKS_API_KEY: str = os.getenv("FIREWORKS_API_KEY", "").strip()
FIREWORKS_BASE_URL: str = os.getenv(
"FIREWORKS_BASE_URL", "https://api.fireworks.ai/inference/v1"
).strip()
# Swap this to any Fireworks model id you like. Coding-strong defaults:
# accounts/fireworks/models/deepseek-v4-pro
# accounts/fireworks/models/kimi-k2p6
FIREWORKS_MODEL: str = os.getenv(
"FIREWORKS_MODEL", "accounts/fireworks/models/deepseek-v4-pro"
).strip()
FIREWORKS_TEMPERATURE: float = float(os.getenv("FIREWORKS_TEMPERATURE", "0.2"))
FIREWORKS_MAX_TOKENS: int = int(os.getenv("FIREWORKS_MAX_TOKENS", "4000"))
# --- Review behavior ---
# If a PR author's login is in this list (case-insensitive), the review
# body will @-mention them. Handles the @openswe bot case.
MENTION_AUTHORS: list[str] = [
a.strip().lower()
for a in os.getenv("MENTION_AUTHORS", "openswe").split(",")
if a.strip()
]
HOST: str = os.getenv("HOST", "127.0.0.1")
PORT: int = int(os.getenv("PORT", "8765"))
@lru_cache
def get_config() -> Config:
return Config()