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
5 changes: 2 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ FROM python:3.11-slim AS runtime
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
AGENTFIELD_SERVER=http://agentfield:8080 \
HARNESS_PROVIDER=opencode \
HARNESS_MODEL=openrouter/moonshotai/kimi-k2.5 \
AI_MODEL=openrouter/moonshotai/kimi-k2.5 \
PR_AF_PROVIDER=opencode \
PR_AF_MODEL=openrouter/moonshotai/kimi-k2.5 \
PORT=8004 \
HOME=/home/praf \
PYTHONPATH=/app/src \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ There are excellent AI code review tools on the market. PR-AF is not designed to

```bash
git clone https://github.com/Agent-Field/pr-af.git && cd pr-af
cp .env.example .env # Add OPENROUTER_API_KEY, GITHUB_TOKEN
cp .env.example .env # Add OPENROUTER_API_KEY, GH_TOKEN
docker compose up --build
```

Expand Down
6 changes: 2 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@ services:
- AGENTFIELD_SERVER=http://agentfield:8080
- AGENTFIELD_API_KEY=${AGENTFIELD_API_KEY:-}
- AGENT_CALLBACK_URL=http://pr-af:8004
- HARNESS_PROVIDER=opencode
- HARNESS_MODEL=${HARNESS_MODEL:-openrouter/moonshotai/kimi-k2.5}
- AI_MODEL=${AI_MODEL:-openrouter/moonshotai/kimi-k2.5}
- PR_AF_PROVIDER=${PR_AF_PROVIDER:-opencode}
- PR_AF_MODEL=${PR_AF_MODEL:-openrouter/moonshotai/kimi-k2.5}
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
- GITHUB_TOKEN=${GITHUB_TOKEN:-}
- GH_TOKEN=${GH_TOKEN:-}
- XDG_DATA_HOME=/home/praf/.local/share
- PR_AF_WORKDIR=/workspaces
Expand Down
4 changes: 2 additions & 2 deletions docs/DX.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ POST /api/v1/execute/async/pr-af.review
- Configurable: `--clone` (full clone), `--shallow` (depth=1), `--no-clone` (API only)

**Authentication:**
- `GITHUB_TOKEN` env var (personal access token or GitHub App installation token)
- `GH_TOKEN` env var (personal access token or GitHub App installation token)
- GitHub App: preferred for CI/CD (fine-grained permissions, higher rate limits)

**Best for:** CI/CD pipelines, GitHub Action triggers, full-featured review.
Expand Down Expand Up @@ -369,7 +369,7 @@ comments:

| Variable | Required | Description |
|---|---|---|
| `GITHUB_TOKEN` | Yes (for GitHub output) | GitHub PAT or App installation token |
| `GH_TOKEN` | Yes (for GitHub output) | GitHub PAT or App installation token |
| `AGENTFIELD_API_KEY` | Yes | AgentField platform API key |
| `OPENROUTER_API_KEY` | Yes | LLM provider API key |
| `PR_AF_CONFIG` | No | Path to config file (default: `.pr-af.yml`) |
Expand Down
4 changes: 2 additions & 2 deletions src/pr_af/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
load_dotenv(_project_root / ".env")

_ai_config = AIIntegrationConfig.from_env()
NODE_ID = os.getenv("PR_AF", "pr-af")
NODE_ID = os.getenv("NODE_ID", "pr-af")
HarnessConfig = _agentfield.HarnessConfig

app = Agent(
Expand Down Expand Up @@ -95,7 +95,7 @@ def _resolve_repo(repo_path: str | None, pr_url: str | None) -> str:
os.makedirs(workdir, exist_ok=True)

clone_url = target
gh_token = os.getenv("GH_TOKEN") or os.getenv("GITHUB_TOKEN", "")
gh_token = os.getenv("GH_TOKEN", "")
if gh_token and clone_url.startswith("https://github.com/"):
clone_url = clone_url.replace("https://github.com/", f"https://{gh_token}@github.com/")

Expand Down
16 changes: 4 additions & 12 deletions src/pr_af/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,17 +238,12 @@ def from_yaml(cls, path: str) -> ReviewConfig:


class AIIntegrationConfig(BaseModel):
provider: str = Field(
default_factory=lambda: os.getenv("PR_AF_PROVIDER", os.getenv("HARNESS_PROVIDER", "opencode"))
)
provider: str = Field(default_factory=lambda: os.getenv("PR_AF_PROVIDER", "opencode"))
harness_model: str = Field(
default_factory=lambda: os.getenv("PR_AF_MODEL", os.getenv("HARNESS_MODEL", "minimax/minimax-m2.5"))
default_factory=lambda: os.getenv("PR_AF_MODEL", "minimax/minimax-m2.5")
)
ai_model: str = Field(
default_factory=lambda: os.getenv(
"PR_AF_AI_MODEL",
os.getenv("AI_MODEL", os.getenv("PR_AF_MODEL", "minimax/minimax-m2.5")),
)
default_factory=lambda: os.getenv("PR_AF_MODEL", "minimax/minimax-m2.5")
)
max_turns: int = Field(default_factory=lambda: int(os.getenv("PR_AF_MAX_TURNS", "50")))
max_retries: int = Field(default_factory=lambda: int(os.getenv("PR_AF_AI_MAX_RETRIES", "3")))
Expand All @@ -257,9 +252,7 @@ class AIIntegrationConfig(BaseModel):
)
max_backoff_seconds: float = Field(default_factory=lambda: float(os.getenv("PR_AF_AI_MAX_BACKOFF_SECONDS", "8.0")))
opencode_bin: str = Field(default_factory=lambda: os.getenv("PR_AF_OPENCODE_BIN", "opencode"))
opencode_server: str | None = Field(
default_factory=lambda: os.getenv("PR_AF_OPENCODE_SERVER", os.getenv("OPENCODE_SERVER"))
)
opencode_server: str | None = Field(default_factory=lambda: os.getenv("PR_AF_OPENCODE_SERVER"))

@classmethod
def from_env(cls) -> AIIntegrationConfig:
Expand All @@ -271,7 +264,6 @@ def provider_env(self) -> dict[str, str]:
"ANTHROPIC_API_KEY",
"OPENAI_API_KEY",
"GOOGLE_API_KEY",
"GITHUB_TOKEN",
"GH_TOKEN",
)
env: dict[str, str] = {key: value for key in env_keys if (value := os.getenv(key))}
Expand Down
4 changes: 2 additions & 2 deletions src/pr_af/github/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def _is_github_app_configured() -> bool:

class GitHubClient:
def __init__(self, token: str | None = None):
self.token = token or os.getenv("GITHUB_TOKEN", "")
self.token = token or os.getenv("GH_TOKEN", "")
self.base_url = "https://api.github.com"
self._use_app_auth = _is_github_app_configured()

Expand Down Expand Up @@ -262,7 +262,7 @@ async def clone_repo(
if self._use_app_auth:
token = await _get_installation_token(owner, repo)
else:
token = os.getenv("GH_TOKEN") or self.token or os.getenv("GITHUB_TOKEN", "")
token = os.getenv("GH_TOKEN") or self.token
if not token:
raise ValueError("GitHub token is required for clone_repo")

Expand Down
Loading