Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .github/workflows/build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- id: uv
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0

- name: Check uv.lock
run: uv lock --check
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
- uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
# SEE https://github.com/pre-commit/action
- uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
2 changes: 1 addition & 1 deletion .github/workflows/provider-smoke.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Setup uv
uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0

- name: Install dependencies
run: uv sync
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ jobs:
with:
python-version: '3.12'

- uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0

- name: Flag missing PyPI publish
if: needs.publish-pypi.result != 'success'
Expand Down
135 changes: 48 additions & 87 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,34 @@


<br />

<div align="center">


<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://codium.ai/images/pr_agent/logo-dark.png" width="330">
<source media="(prefers-color-scheme: light)" srcset="https://codium.ai/images/pr_agent/logo-light.png" width="330">
<img src="https://codium.ai/images/pr_agent/logo-light.png" alt="logo" width="330">

<source media="(prefers-color-scheme: dark)" srcset="https://your-org.dev/images/diffmind/logo-dark.png" width="330">
<source media="(prefers-color-scheme: light)" srcset="https://your-org.dev/images/diffmind/logo-light.png" width="330">
<img src="https://your-org.dev/images/diffmind/logo-light.png" alt="logo" width="330">
</picture>
<br>
The Original Open-Source PR Reviewer
An Open-Source AI PR Reviewer
<br><br>
<a href="https://github.com/the-pr-agent/pr-agent/commits/main">
<img alt="GitHub" src="https://img.shields.io/github/last-commit/the-pr-agent/pr-agent/main?style=for-the-badge" height="20">
<a href="https://github.com/your-org/DiffMind/commits/main">
<img alt="GitHub" src="https://img.shields.io/github/last-commit/your-org/DiffMind/main?style=for-the-badge" height="20">
</a>
</div>

---

This repository contains the open-source PR Agent Project.
It is not the Qodo offering for open-source projects.

PR-Agent is an open-source, AI-powered code review agent and a community-maintained legacy project of Qodo. It is distinct from Qodo's primary AI code review offering, which provides a feature-rich, context-aware experience. Qodo offers a free version for open-source projects and integrates seamlessly with GitHub, GitLab, Bitbucket, and Azure DevOps for high-quality automated reviews.
This repository contains the open-source DiffMind project.

DiffMind is an open-source, AI-powered code review agent that helps teams ship better pull requests faster. It plugs into your existing Git workflow and gives you automated, context-aware reviews without locking you into any single vendor.

## Sponsors

PR-Agent is a community-maintained open-source project, with its ongoing development supported by our sponsors. If you'd like to support the project, consider [becoming a sponsor](https://github.com/sponsors/naorpeled).

<p align="center">
<h3 align="center">🥇 Gold Sponsor</h3>
</p>

<p align="center">
<a target="_blank" href="https://www.qodo.ai/">
<img alt="Qodo — Gold sponsor" src="https://www.qodo.ai/wp-content/uploads/2025/03/qodo-logo.svg" width="300">
</a>
</p>

<p align="center">
<a target="_blank" href="https://www.qodo.ai/solutions/open-source/">Free version of Qodo for open-source projects</a>
</p>

DiffMind is a community-maintained open-source project. If you'd like to support the project, consider [becoming a sponsor](https://github.com/sponsors/your-org).

## Table of Contents

- [Getting Started](#getting-started)
- [Why Use PR-Agent?](#why-use-pr-agent)
- [Why Use DiffMind?](#why-use-diffmind)
- [Features](#features)
- [See It in Action](#see-it-in-action)
- [How It Works](#how-it-works)
Expand All @@ -59,68 +38,67 @@ PR-Agent is a community-maintained open-source project, with its ongoing develop
## Getting Started

> [!NOTE]
> **Docker Hub namespace migration.** Releases `0.34.2` and later are published under [`pragent/pr-agent`](https://hub.docker.com/r/pragent/pr-agent). Older releases (up to and including `v0.31`) remain available at the legacy [`codiumai/pr-agent`](https://hub.docker.com/r/codiumai/pr-agent) namespace as a frozen archive — no new images are pushed there. Update any pinned `image:` / `docker pull` / `uses: docker://` references when upgrading to `0.34.2+`.
> **Docker Hub namespace.** Images are published under [`your-org/diffmind`](https://hub.docker.com/r/your-org/diffmind). Update any pinned `image:` / `docker pull` / `uses: docker://` references when upgrading.

### 🚀 Quick Start for PR-Agent
### 🚀 Quick Start for DiffMind

#### 1. GitHub Action (Recommended)

Add automated PR reviews to your repository with a simple workflow file:

```yaml
# .github/workflows/pr-agent.yml
name: PR Agent
# .github/workflows/diffmind.yml
name: DiffMind
on:
pull_request:
types: [opened, synchronize]
jobs:
pr_agent_job:
diffmind_job:
runs-on: ubuntu-latest
steps:
- name: PR Agent action step
uses: the-pr-agent/pr-agent@main
- name: DiffMind action step
uses: your-org/DiffMind@main
env:
OPENAI_KEY: ${{ secrets.OPENAI_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
[Full GitHub Action setup guide](https://docs.pr-agent.ai/installation/github/#run-as-a-github-action)
[Full GitHub Action setup guide](https://docs.diffmind.dev/installation/github/#run-as-a-github-action)

#### 2. CLI Usage (Local Development)

Run PR-Agent locally on your repository:
Run DiffMind locally on your repository:

```bash
pip install pr-agent
pip install diffmind
export OPENAI_KEY=your_key_here
pr-agent --pr_url https://github.com/owner/repo/pull/123 review
diffmind --pr_url https://github.com/owner/repo/pull/123 review
```
[Complete CLI setup guide](https://docs.pr-agent.ai/usage-guide/automations_and_usage/#local-repo-cli)
[Complete CLI setup guide](https://docs.diffmind.dev/usage-guide/automations_and_usage/#local-repo-cli)

#### 3. Other Platforms

- [GitLab webhook setup](https://docs.pr-agent.ai/installation/gitlab/)
- [BitBucket app installation](https://docs.pr-agent.ai/installation/bitbucket/)
- [Azure DevOps setup](https://docs.pr-agent.ai/installation/azure/)
- [GitLab webhook setup](https://docs.diffmind.dev/installation/gitlab/)
- [BitBucket app installation](https://docs.diffmind.dev/installation/bitbucket/)
- [Azure DevOps setup](https://docs.diffmind.dev/installation/azure/)

## News and Updates

Full notes for every release are on the [Releases page](https://github.com/the-pr-agent/pr-agent/releases).

Full notes for every release are on the [Releases page](https://github.com/your-org/DiffMind/releases).

## Why Use PR-Agent?
## Why Use DiffMind?

### 🎯 Built for Real Development Teams

**Fast & Affordable**: Each tool (`/review`, `/improve`, `/ask`) uses a single LLM call (~30 seconds, low cost)

**Handles Any PR Size**: Our [PR Compression strategy](https://docs.pr-agent.ai/core-abilities/#pr-compression-strategy) effectively processes both small and large PRs
**Handles Any PR Size**: Our PR compression strategy effectively processes both small and large PRs

**Highly Customizable**: JSON-based prompting allows easy customization of review categories and behavior via [configuration files](pr_agent/settings/configuration.toml)
**Highly Customizable**: JSON-based prompting allows easy customization of review categories and behavior via configuration files (`diffmind/settings/configuration.toml`)

**Platform Agnostic**:
- **Git Providers**: GitHub, GitLab, BitBucket, Azure DevOps, Gitea
- **Deployment**: CLI, GitHub Actions, Docker, self-hosted, webhooks
- **AI Models**: OpenAI GPT, Anthropic Claude, Google Gemini, DeepSeek, Mistral, and any other model reachable through LiteLLM (Azure OpenAI, AWS Bedrock, Vertex AI, Databricks, OpenRouter, Ollama, and more) — see [Changing a model](https://docs.pr-agent.ai/usage-guide/changing_a_model/)
- **AI Models**: OpenAI GPT, Anthropic Claude, Google Gemini, DeepSeek, Mistral, and any other model reachable through LiteLLM (Azure OpenAI, AWS Bedrock, Vertex AI, Databricks, OpenRouter, Ollama, and more) — see [Changing a model](https://docs.diffmind.dev/usage-guide/changing_a_model/)

**Open Source Benefits**:
- Full control over your data and infrastructure
Expand All @@ -132,39 +110,37 @@ Full notes for every release are on the [Releases page](https://github.com/the-p

<div style="text-align:left;">

See the current [feature and git provider support matrix](https://docs.pr-agent.ai/#features) in the PR-Agent documentation.

⚠️ `/help_docs` is temporarily disabled since `v0.36.1` pending a fix for a credential-exposure issue ([#2445](https://github.com/the-pr-agent/pr-agent/issues/2445)).
See the current feature and git-provider support matrix in the DiffMind documentation.

[//]: # (- Support for additional git providers is described in [here]&#40;./docs/Full_environments.md&#41;)
___

## See It in Action

</div>
<h4><a href="https://github.com/the-pr-agent/pr-agent/pull/530">/describe</a></h4>

<h4><a href="https://github.com/your-org/DiffMind/pull/1">/describe</a></h4>
<div align="center">
<p float="center">
<img src="https://www.codium.ai/images/pr_agent/describe_new_short_main.png" width="512">
<img src="https://your-org.dev/images/diffmind/describe_new_short_main.png" width="512">
</p>
</div>
<hr>

<h4><a href="https://github.com/the-pr-agent/pr-agent/pull/732#issuecomment-1975099151">/review</a></h4>
<h4><a href="https://github.com/your-org/DiffMind/pull/1#issuecomment-1">/review</a></h4>
<div align="center">
<p float="center">
<kbd>
<img src="https://www.codium.ai/images/pr_agent/review_new_short_main.png" width="512">
<img src="https://your-org.dev/images/diffmind/review_new_short_main.png" width="512">
</kbd>
</p>
</div>
<hr>

<h4><a href="https://github.com/the-pr-agent/pr-agent/pull/732#issuecomment-1975099159">/improve</a></h4>
<h4><a href="https://github.com/your-org/DiffMind/pull/1#issuecomment-2">/improve</a></h4>
<div align="center">
<p float="center">
<kbd>
<img src="https://www.codium.ai/images/pr_agent/improve_new_short_main.png" width="512">
<img src="https://your-org.dev/images/diffmind/improve_new_short_main.png" width="512">
</kbd>
</p>
</div>
Expand All @@ -173,7 +149,7 @@ ___

### Usage Examples

PR-Agent tools run as a comment on a PR or from the CLI. A few common ones:
DiffMind tools run as a comment on a PR or from the CLI. A few common ones:

```bash
# Comment on a PR (GitHub/GitLab/Bitbucket/…):
Expand All @@ -186,48 +162,33 @@ PR-Agent tools run as a comment on a PR or from the CLI. A few common ones:
/similar_issue # find similar issues in the repository

# Or locally via the CLI:
pr-agent --pr_url <PR_URL> review
pr-agent --issue_url <ISSUE_URL> similar_issue
diffmind --pr_url <PR_URL> review
diffmind --issue_url <ISSUE_URL> similar_issue
```

See the [Tools docs](https://docs.pr-agent.ai/tools/#usage-examples) for the full list of tools with example commands, and each tool's page for screenshots and options.
See the Tools docs for the full list of tools with example commands, and each tool's page for screenshots and options.

<hr>

## How It Works

The following diagram illustrates PR-Agent tools and their flow:
The following diagram illustrates DiffMind tools and their flow:

![PR-Agent Tools](https://www.qodo.ai/images/pr_agent/diagram-v0.9.png)
![DiffMind Tools](https://your-org.dev/images/diffmind/diagram-v0.1.png)

## Data Privacy

### Self-hosted PR-Agent
### Self-hosted DiffMind

- If you host PR-Agent with your OpenAI API key, it is between you and OpenAI. You can read their API data privacy policy here:
- If you host DiffMind with your own OpenAI API key, data handling is between you and OpenAI. You can read their API data privacy policy here:
https://openai.com/enterprise-privacy

## Contributing

To contribute to the project, get started by reading our [Contributing Guide](https://github.com/the-pr-agent/pr-agent/blob/main/CONTRIBUTING.md).
To contribute to the project, get started by reading our [Contributing Guide](https://github.com/your-org/DiffMind/blob/main/CONTRIBUTING.md).

For local verification, run `PYTHONPATH=. uv run pytest` from the repository root; it discovers the unit-test suite under `tests/unittest` by default. End-to-end tests under `tests/e2e_tests` require provider credentials and should be invoked explicitly, for example `PYTHONPATH=. uv run pytest tests/e2e_tests/test_github_app.py`.


## Big News for PR-Agent

PR-Agent has a new home!

After years of building this tool alongside the community, Qodo has donated PR-Agent to the open-source community - and we couldn't be more excited about what comes next.

The project now lives in the PR-Agent org on GitHub, is fully community-owned, and is open for contributions and additional maintainers.

What else changed:
- Docs moved to - [docs.pr-agent.ai](https://docs.pr-agent.ai/)
- Qodo Merge (Qodo 1.0), the hosted URL, which was the enterprise version of PR-Agent, has been rebranded and evolved into Qodo (Qodo 2.0), a full AI code review platform.

## ❤️ Community

This open-source release remains here as a community contribution from Qodo — the origin of modern AI-powered code collaboration. We’re proud to share it and inspire developers worldwide.

The project now has its first external maintainer, Naor ([@naorpeled](https://github.com/naorpeled)), and is currently in the process of being donated to an open-source foundation.
DiffMind is community-owned and open for contributions and additional maintainers. If you'd like to get involved, open an issue or a PR!
6 changes: 3 additions & 3 deletions docs/docs/installation/github.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ When you open your next PR, you should see a comment from `github-actions` bot w
# ... previous environment values
OPENAI.ORG: "<Your organization name under your OpenAI account>"
PR_REVIEWER.REQUIRE_TESTS_REVIEW: "false" # Disable tests review
PR_CODE_SUGGESTIONS.NUM_CODE_SUGGESTIONS: 6 # Increase number of code suggestions
PR_CODE_SUGGESTIONS.NUM_CODE_SUGGESTIONS_PER_CHUNK: 6 # Increase number of code suggestions
```

See detailed usage instructions in the [USAGE GUIDE](../usage-guide/automations_and_usage.md#github-action)
Expand Down Expand Up @@ -380,7 +380,7 @@ Configure for specific programming languages:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Language-specific settings
pr_reviewer.extra_instructions: "Focus on Python best practices, type hints, and docstrings."
pr_code_suggestions.num_code_suggestions: "8"
pr_code_suggestions.num_code_suggestions_per_chunk: "8"
pr_code_suggestions.suggestions_score_threshold: "7"
# Tool configuration
github_action_config.auto_review: "true"
Expand Down Expand Up @@ -459,7 +459,7 @@ fallback_models = ["anthropic/claude-opus-5"]
extra_instructions = "Focus on security issues and code quality."

[pr_code_suggestions]
num_code_suggestions = 6
num_code_suggestions_per_chunk = 6
suggestions_score_threshold = 7
```

Expand Down
15 changes: 13 additions & 2 deletions pr_agent/algo/pr_processing.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from __future__ import annotations

import asyncio
import traceback
from contextvars import ContextVar
from dataclasses import dataclass, replace
from typing import Callable, List, Tuple

import openai

from pr_agent.algo.git_patch_processing import (
decouple_and_convert_to_hunks_with_lines_numbers,
extend_patch,
Expand All @@ -13,7 +16,7 @@
from pr_agent.algo.language_handler import sort_files_by_main_languages
from pr_agent.algo.model_routing import route_primary_model
from pr_agent.algo.run_details import record_model_used
from pr_agent.algo.token_budget import AttemptTokenBudget, clip_tokens
from pr_agent.algo.token_budget import AttemptTokenBudget, FallbackEligibleError, clip_tokens
from pr_agent.algo.token_handler import TokenHandler
from pr_agent.algo.types import EDIT_TYPE
from pr_agent.algo.utils import ModelType, get_model
Expand All @@ -31,6 +34,7 @@
OUTPUT_BUFFER_TOKENS_HARD_THRESHOLD = 1000
MAX_EXTRA_LINES = 10


_effective_fallback_chain: ContextVar[tuple[tuple[str, str | None], ...] | None] = ContextVar(
"pr_agent_effective_fallback_chain", default=None
)
Expand Down Expand Up @@ -667,6 +671,7 @@ async def retry_with_fallback_models(f: Callable, model_type: ModelType = ModelT
effective_chain = tuple(zip(all_models, all_deployments[:len(all_models)], strict=True))
original_deployment_id = get_settings().get("openai.deployment_id", None)
context_token = _effective_fallback_chain.set(effective_chain)
attempt_errors = []
try:
# try each (model, deployment_id) pair until one is successful, otherwise raise exception
for i, (model, deployment_id) in enumerate(effective_chain):
Expand All @@ -678,12 +683,18 @@ async def retry_with_fallback_models(f: Callable, model_type: ModelType = ModelT
get_settings().set("openai.deployment_id", deployment_id)
result = await f(model)
except Exception as e:
if not isinstance(e, (openai.APIError, asyncio.TimeoutError, FallbackEligibleError)):
raise
attempt_errors.append(f"{model}: {type(e).__name__}: {e}")
get_logger().warning(
f"Failed to generate prediction with {model}",
artifact={"error": e},
)
if i == len(all_models) - 1: # If it's the last iteration
raise Exception(f"Failed to generate prediction with any model of {all_models}") from e
raise Exception(
f"Failed to generate prediction with any model of {all_models}. "
f"Attempts: {'; '.join(attempt_errors)}"
) from e
else:
record_model_used(model, is_fallback=i > 0)
return result
Expand Down
Loading
Loading