Compare commits

..

80 Commits

Author SHA1 Message Date
2fc0e462c4 docs: update describe tool configuration table with missing options 2025-02-16 15:36:18 +02:00
3f1987248e docs: add override title config by tag name option to describe tool table 2025-02-16 15:21:42 +02:00
778d00d1a0 Merge remote-tracking branch 'origin/main' 2025-02-15 11:32:43 +02:00
cc8d5a6c50 docs: fix broken links in GitLab Server installation section 2025-02-15 11:32:32 +02:00
Tal
62c47f9cb5 Merge pull request #1536 from PeterDaveHelloKitchen/OptimizeDockerfile
Use `pip install` with `--no-cache-dir` in `Dockerfile.github_action`
2025-02-15 11:25:41 +02:00
bb31b0c66b docs: update Qodo Merge installation guide with GitLab Server details 2025-02-15 11:23:52 +02:00
Tal
359c963ad1 Merge pull request #1531 from hi120ki/add-pull-request-target-event
Add : pull_request_target event on GitHub Actions integration
2025-02-15 08:08:20 +02:00
130b1ff4fb Use pip install with --no-cache-dir in Dockerfile.github_action 2025-02-15 00:17:02 +08:00
Tal
605a4b99ad Merge pull request #1534 from qodo-ai/tr/help_r
feat: improve help tool with markdown header formatting and error han…
2025-02-13 11:50:59 +02:00
b989f41b96 fix: correct typo in help tool message ("be" -> "can be") 2025-02-13 11:48:07 +02:00
26168a605b fix: correct typo in help tool message ("be" -> "can be") 2025-02-13 11:47:21 +02:00
2c37b02aa0 feat: improve help tool with markdown header formatting and error handling 2025-02-13 11:44:50 +02:00
Tal
a2550870c2 Merge pull request #1532 from qodo-ai/tr/review_effort
fix: update review effort label format to use X/5 notation
2025-02-13 09:25:53 +02:00
279c6ead8f fix: update review effort label format to use X/5 notation 2025-02-13 08:41:25 +02:00
c9500cf796 Add : pull_request_target event on GitHub Actions integration
Signed-off-by: Hi120ki <12624257+hi120ki@users.noreply.github.com>
2025-02-13 12:03:30 +09:00
77204faa51 docs: clarify open-source models usage scope in model selection guide 2025-02-11 10:24:16 +02:00
43fb8ff433 docs: fix broken link to Qodo Merge models documentation 2025-02-11 08:49:05 +02:00
cd129d8b27 docs: fix broken link to Qodo Merge models documentation 2025-02-11 08:47:04 +02:00
Tal
04aff0d3b2 Update README.md 2025-02-07 20:51:21 +02:00
Tal
be1dd4bd20 Update README.md 2025-02-06 18:10:37 +02:00
Tal
b3b89e7138 Merge pull request #1522 from qodo-ai/tr/readme_34
docs: update README with new design and remove outdated news
2025-02-06 18:06:17 +02:00
9045723084 docs: adjust Qodo Merge link formatting in README 2025-02-06 18:04:31 +02:00
34e22a2c8e docs: update image URL in README for /improve tool screenshot 2025-02-06 18:02:40 +02:00
1d784c60cb docs: update README with new design and remove outdated news 2025-02-06 17:59:40 +02:00
deffdbbb89 Merge pull request #1517 from qodo-ai/security_policy_md
Create SECURITY.md
2025-02-05 14:54:55 +02:00
b29a19957c Update SECURITY.md
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-05 14:54:32 +02:00
f209bc5323 Update SECURITY.md 2025-02-05 14:50:12 +02:00
32890fec20 Create SECURITY.md 2025-02-05 14:03:32 +02:00
Tal
9ddd7c967a Merge pull request #1515 from qodo-ai/create-code-of-conduct
Create CODE_OF_CONDUCT.md
2025-02-05 11:28:10 +02:00
Tal
245c3ad523 Update CODE_OF_CONDUCT.md
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-05 11:27:51 +02:00
43decd9ff2 Update CODE_OF_CONDUCT.md 2025-02-05 11:25:06 +02:00
Tal
3af84aab5b Merge pull request #1514 from qodo-ai/tr/improve_impact
feat: improve code suggestions table with impact levels and styling
2025-02-05 11:20:16 +02:00
3633863e90 Create CODE_OF_CONDUCT.md 2025-02-05 10:41:24 +02:00
69f19f1abd feat: improve code suggestions impact levels with configurable thresholds 2025-02-05 09:41:01 +02:00
400146985a feat: improve code suggestions table with impact levels and styling 2025-02-05 09:31:32 +02:00
24bf875db6 fix: handle GitHub permission errors when editing comments 2025-02-03 07:51:44 +02:00
9687b4df70 docs: update model selection guide with supported models list 2025-02-03 07:31:02 +02:00
Tal
d8fba02b48 Merge pull request #1509 from KennyDizi/main
Define user_message_only_models list for using user prompt only model
2025-02-02 16:14:05 +02:00
a6482c37ce Add o3-mini to user message only model list 2025-02-02 18:03:38 +07:00
83582bc935 Add support o3-mini model 2025-02-02 18:02:53 +07:00
4ac1e15bae Refactoring user messages only flow 2025-02-02 18:01:44 +07:00
a48686bde9 Define USER_MESSAGE_ONLY_MODELS in the algo init file 2025-02-02 18:01:16 +07:00
7168d16386 Remove user_message_only_models from configuration file 2025-02-02 18:00:34 +07:00
Tal
dc21f71ee2 Merge pull request #1510 from PeterDaveHelloKitchen/OptimizeDockerfile
Use `pip install` with `--no-cache-dir` in Dockerfiles
2025-02-02 07:30:13 +02:00
7127a030b2 fix: improve error logging in GitHub polling service 2025-02-01 19:47:54 +02:00
8f340bce67 Use pip install with --no-cache-dir in Dockerfiles
This will help minimize the Docker image size, as below:

```
REPOSITORY    TAG       IMAGE ID         CREATED        SIZE
pr-agent      after     caed11a1ed9c     2 hours ago    1.48GB
pr-agent      before    d6f12eb987b8     3 hours ago    1.59GB
```
2025-02-02 00:29:52 +08:00
48377e3c81 Add a null check for user_message_only_models before using it 2025-01-31 11:53:05 +07:00
7eb26b3220 Check current model is in user_message_only_models list 2025-01-31 11:25:51 +07:00
32ccb25575 Add user_message_only_models 2025-01-31 11:24:43 +07:00
9aafe18f01 docs: add platform support notice for implement tool 2025-01-30 12:24:14 +02:00
Tal
4df9e03c4c Merge pull request #1506 from qodo-ai/tr/fallback
fix: add fallback for parsing AI responses with leading '+' symbols
2025-01-30 11:56:04 +02:00
136c75a5ac fix: add fallback for parsing AI responses with leading '+' symbols 2025-01-30 08:35:31 +02:00
91b0f11cf2 docs: add link to article about effective AI code suggestions 2025-01-30 07:44:09 +02:00
Tal
50740f080b Merge pull request #1500 from qodo-ai/of/add-contributing-file
Add CONTRIBUTING.md with contribution guidelines and setup instructions
2025-01-28 15:39:49 +02:00
ad5308c0a3 docs: add CONTRIBUTING.md with development guidelines and setup instructions 2025-01-28 11:55:27 +02:00
Tal
f383709629 Merge pull request #1498 from qodo-ai/tr/issue_formatting
fix: update issue template fields and Discord link
2025-01-28 10:07:18 +02:00
4d7fe07c16 fix: update issue template fields and Discord link 2025-01-28 09:59:59 +02:00
Tal
456d5aa233 Merge pull request #1495 from qodo-ai/of/issue_template
fix: remove shell rendering from issue templates
2025-01-28 09:21:13 +02:00
d50bfa4b06 fix: remove shell rendering from issue templates 2025-01-28 09:18:02 +02:00
7393887381 Merge remote-tracking branch 'origin/main' 2025-01-28 08:36:47 +02:00
9da4c9d776 fix: correct typo in code suggestions label description 2025-01-28 08:36:36 +02:00
Tal
251b4a6395 Update README.md 2025-01-28 03:29:44 +02:00
Tal
d85725c636 Merge pull request #1490 from qodo-ai/of/issues-fixes
Update config.yml
2025-01-27 16:25:24 +02:00
6ef586a617 Update miscellaneous.yml 2025-01-27 16:24:40 +02:00
43991df2c4 Update bug-report.yml 2025-01-27 16:23:48 +02:00
231d5c20d5 Update config.yml 2025-01-27 16:22:35 +02:00
Tal
9052cec391 Merge pull request #1478 from qodo-ai/of/issue_template
Add GitHub issue templates for bug reports and feature requests
2025-01-27 16:21:17 +02:00
Tal
33ed6927fc Update .github/ISSUE_TEMPLATE/miscellaneous.yml
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-01-27 16:21:11 +02:00
62aaeb267a Update bug-report.yml 2025-01-27 16:20:24 +02:00
a7bea3b166 feat: add miscellaneous issue template and update template configurations 2025-01-27 16:17:33 +02:00
b81d686561 Update feature-request.yml 2025-01-27 16:02:29 +02:00
e5e30f7bd3 Update bug-report.yml 2025-01-27 16:00:03 +02:00
84d81deac0 Merge branch 'main' into of/issue_template 2025-01-26 09:23:54 +02:00
Tal
c4a70f4852 Update .github/ISSUE_TEMPLATE/bug-report.yml
Co-authored-by: qodo-merge-pro[bot] <151058649+qodo-merge-pro[bot]@users.noreply.github.com>
2025-01-23 16:52:22 +02:00
Tal
363ea3eec8 Update .github/ISSUE_TEMPLATE/bug-report.yml
Co-authored-by: qodo-merge-pro[bot] <151058649+qodo-merge-pro[bot]@users.noreply.github.com>
2025-01-23 16:51:12 +02:00
97cbfe1c2b fix: update issue template labels and descriptions for git providers and bug types 2025-01-23 16:27:26 +02:00
68f2198549 feat: update issue template dropdowns for git providers and task types 2025-01-23 16:11:30 +02:00
20bbe4187a docs: reorder contact links in issue template config 2025-01-23 15:57:13 +02:00
2f69c8989c clean-up 2025-01-23 13:38:02 +02:00
ed102dc730 feat: add GitHub issue templates for bug reports and feature requests 2025-01-23 13:35:30 +02:00
34 changed files with 469 additions and 99 deletions

38
.github/ISSUE_TEMPLATE/bug-report.yml vendored Normal file
View File

@ -0,0 +1,38 @@
name: "\U0001FAB2 Bug Report"
description: Submit a bug report
labels: ["bug"]
body:
- type: dropdown
id: information-git-provider
attributes:
label: Git provider
description: 'The problem arises when using:'
options:
- "Github Cloud"
- "Github Enterprise"
- "Gitlab"
- "Bitbucket Cloud"
- "Bitbucket Server"
- "Azure"
- "Other"
validations:
required: true
- type: textarea
id: system-info
attributes:
label: System Info
description: Please share your system info with us.
placeholder: model used, deployment type (action/app/cli/...), etc...
validations:
required: true
- type: textarea
id: bug-details
attributes:
label: Bug details
description: Please describe the problem.
placeholder: Describe the problem
validations:
required: true

10
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,10 @@
blank_issues_enabled: false
version: 0.1
contact_links:
- name: Discussions
url: https://github.com/qodo-ai/pr-agent/discussions
about: GitHub Discussions
- name: Discord community
url: https://discord.com/channels/1057273017547378788/1126104260430528613
about: Join our discord community

View File

@ -0,0 +1,21 @@
name: "\U0001F4A1 Feature request"
description: Submit a proposal/request for a new PR-Agent feature
labels: ["feature"]
body:
- type: textarea
id: feature-request
validations:
required: true
attributes:
label: Feature request
description: |
Description of the feature proposal.
- type: textarea
id: motivation
validations:
required: true
attributes:
label: Motivation
description: |
Outline the motivation for the proposal.

View File

@ -0,0 +1,36 @@
name: "❔ General Issue"
description: Submit a general issue
labels: ["general"]
body:
- type: dropdown
id: information-git-provider
attributes:
label: Git provider (optional)
description: 'Git Provider:'
options:
- "Github Cloud"
- "Github Enterprise"
- "Gitlab"
- "Bitbucket Cloud"
- "Bitbucket Server"
- "Azure"
- "Other"
- type: textarea
id: system-info
attributes:
label: System Info (optional)
description: Please share your system info with us.
placeholder: model used, deployment type (action/app/cli/...), etc...
validations:
required: false
- type: textarea
id: issues-details
attributes:
label: Issues details
description: Please share the issues details.
placeholder: Describe the issue
validations:
required: true

45
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,45 @@
# Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of fostering an open
and welcoming community, we pledge to respect all people who contribute through reporting
issues, posting feature requests, updating documentation, submitting pull requests or
patches, and other activities.
We are committed to making participation in this project a harassment-free experience for
everyone, regardless of level of experience, gender, gender identity and expression,
sexual orientation, disability, personal appearance, body size, race, ethnicity, age,
religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic addresses,
without explicit permission
* Other unethical or unprofessional conduct
Project maintainers have the right and responsibility to remove, edit, or reject comments,
commits, code, wiki edits, issues, and other contributions that are not aligned to this
Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors
that they deem inappropriate, threatening, offensive, or harmful.
By adopting this Code of Conduct, project maintainers commit themselves to fairly and
consistently applying these principles to every aspect of managing this project. Project
maintainers who do not follow or enforce the Code of Conduct may be permanently removed
from the project team.
This Code of Conduct applies both within project spaces and in public spaces when an
individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
contacting a project maintainer at tal.r@qodo.ai . All complaints will
be reviewed and investigated and will result in a response that is deemed necessary and
appropriate to the circumstances. Maintainers are obligated to maintain confidentiality
with regard to the reporter of an incident.
This Code of Conduct is adapted from the
[Contributor Covenant](https://contributor-covenant.org), version 1.3.0, available at
[contributor-covenant.org/version/1/3/0/](https://contributor-covenant.org/version/1/3/0/)

38
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,38 @@
# Contributing to PR-Agent
Thank you for your interest in contributing to the PR-Agent project!
## Getting Started
1. Fork the repository and clone your fork
2. Install Python 3.10 or higher
3. Install dependencies (`requirements.txt` and `requirements-dev.txt`)
4. Create a new branch for your contribution:
- For new features: `git checkout -b feature/your-feature-name`
- For bug fixes: `git checkout -b fix/issue-description`
5. Make your changes
6. Write or update tests as needed
7. Run tests locally to ensure everything passes
8. Commit your changes using conventional commit messages
9. Push to your fork and submit a pull request
## Development Guidelines
- Keep pull requests focused on a single feature or fix
- Follow the existing code style and formatting conventions
- Add unit tests for any new functionality using pytest
- Ensure test coverage for your changes
- Update documentation as needed
## Pull Request Process
1. Ensure your PR includes a clear description of the changes
2. Link any related issues
3. Update the README.md if needed
4. Wait for review from maintainers
## Questions or Need Help?
- Join our [Discord community](https://discord.com/channels/1057273017547378788/1126104260430528613) for questions and discussions
- Check the [documentation](https://qodo-merge-docs.qodo.ai/) for detailed information
- Report bugs or request features through [GitHub Issues](https://github.com/qodo-ai/pr-agent/issues)

View File

@ -3,7 +3,7 @@ FROM python:3.12 as base
WORKDIR /app
ADD pyproject.toml .
ADD requirements.txt .
RUN pip install . && rm pyproject.toml requirements.txt
RUN pip install --no-cache-dir . && rm pyproject.toml requirements.txt
ENV PYTHONPATH=/app
ADD docs docs
ADD pr_agent pr_agent

View File

@ -10,6 +10,12 @@
</picture>
<br/>
[Installation Guide](https://qodo-merge-docs.qodo.ai/installation/) |
[Usage Guide](https://qodo-merge-docs.qodo.ai/usage-guide/) |
[Tools Guide](https://qodo-merge-docs.qodo.ai/tools/) |
[Qodo Merge](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/) 💎
PR-Agent aims to help efficiently review and handle pull requests, by providing AI feedback and suggestions
</div>
@ -22,13 +28,16 @@ PR-Agent aims to help efficiently review and handle pull requests, by providing
</a>
</div>
### [Documentation](https://qodo-merge-docs.qodo.ai/)
[//]: # (### [Documentation]&#40;https://qodo-merge-docs.qodo.ai/&#41;)
- See the [Installation Guide](https://qodo-merge-docs.qodo.ai/installation/) for instructions on installing PR-Agent on different platforms.
[//]: # ()
[//]: # (- See the [Installation Guide]&#40;https://qodo-merge-docs.qodo.ai/installation/&#41; for instructions on installing PR-Agent on different platforms.)
- See the [Usage Guide](https://qodo-merge-docs.qodo.ai/usage-guide/) for instructions on running PR-Agent tools via different interfaces, such as CLI, PR Comments, or by automatically triggering them when a new PR is opened.
[//]: # ()
[//]: # (- See the [Usage Guide]&#40;https://qodo-merge-docs.qodo.ai/usage-guide/&#41; for instructions on running PR-Agent tools via different interfaces, such as CLI, PR Comments, or by automatically triggering them when a new PR is opened.)
- See the [Tools Guide](https://qodo-merge-docs.qodo.ai/tools/) for a detailed description of the different tools, and the available configurations for each tool.
[//]: # ()
[//]: # (- See the [Tools Guide]&#40;https://qodo-merge-docs.qodo.ai/tools/&#41; for a detailed description of the different tools, and the available configurations for each tool.)
## Table of Contents
@ -37,12 +46,17 @@ PR-Agent aims to help efficiently review and handle pull requests, by providing
- [Overview](#overview)
- [Example results](#example-results)
- [Try it now](#try-it-now)
- [Qodo Merge 💎](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/)
- [Qodo Merge](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/)
- [How it works](#how-it-works)
- [Why use PR-Agent?](#why-use-pr-agent)
## News and Updates
### Feb 6, 2025
New design for the `/improve` tool:
<kbd><img src="https://github.com/user-attachments/assets/26506430-550e-469a-adaa-af0a09b70c6d" width="512"></kbd>
### Jan 25, 2025
The open-source GitHub organization was updated:
@ -69,40 +83,7 @@ Update logic and [documentation](https://qodo-merge-docs.qodo.ai/usage-guide/cha
### December 30, 2024
Following [feedback](https://research.kudelskisecurity.com/2024/08/29/careful-where-you-code-multiple-vulnerabilities-in-ai-powered-pr-agent/) from the community, we have addressed two vulnerabilities identified in the open-source PR-Agent project. The fixes are now included in the newly released version (v0.26), available as of today.
### December 25, 2024
The `review` tool previously included a legacy feature for providing code suggestions (controlled by '--pr_reviewer.num_code_suggestion'). This functionality has been deprecated. Use instead the [`improve`](https://qodo-merge-docs.qodo.ai/tools/improve/) tool, which offers higher quality and more actionable code suggestions.
### December 2, 2024
Open-source repositories can now freely use Qodo Merge, and enjoy easy one-click installation using a marketplace [app](https://github.com/apps/qodo-merge-pro-for-open-source).
<kbd><img src="https://github.com/user-attachments/assets/b0838724-87b9-43b0-ab62-73739a3a855c" width="512"></kbd>
See [here](https://qodo-merge-docs.qodo.ai/installation/pr_agent_pro/) for more details about installing Qodo Merge for private repositories.
### November 18, 2024
A new mode was enabled by default for code suggestions - `--pr_code_suggestions.focus_only_on_problems=true`:
- This option reduces the number of code suggestions received
- The suggestions will focus more on identifying and fixing code problems, rather than style considerations like best practices, maintainability, or readability.
- The suggestions will be categorized into just two groups: "Possible Issues" and "General".
Still, if you prefer the previous mode, you can set `--pr_code_suggestions.focus_only_on_problems=false` in the [configuration file](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/).
**Example results:**
Original mode
<kbd><img src="https://qodo.ai/images/pr_agent/code_suggestions_original_mode.png" width="512"></kbd>
Focused mode
<kbd><img src="https://qodo.ai/images/pr_agent/code_suggestions_focused_mode.png" width="512"></kbd>
Following feedback from the community, we have addressed two vulnerabilities identified in the open-source PR-Agent project. The [fixes](https://github.com/qodo-ai/pr-agent/pull/1425) are now included in the newly released version (v0.26), available as of today.
## Overview

62
SECURITY.md Normal file
View File

@ -0,0 +1,62 @@
# Security Policy
PR-Agent is an open-source tool to help efficiently review and handle pull requests. Qodo Merge is a paid version of PR-Agent, designed for companies and teams that require additional features and capabilities.
This document describes the security policy of PR-Agent. For Qodo Merge's security policy, see [here](https://qodo-merge-docs.qodo.ai/overview/data_privacy/#qodo-merge).
## PR-Agent Self-Hosted Solutions
When using PR-Agent with your OpenAI (or other LLM provider) API key, the security relationship is directly between you and the provider. We do not send your code to Qodo servers.
Types of [self-hosted solutions](https://qodo-merge-docs.qodo.ai/installation):
- Locally
- GitHub integration
- GitLab integration
- BitBucket integration
- Azure DevOps integration
## PR-Agent Supported Versions
This section outlines which versions of PR-Agent are currently supported with security updates.
### Docker Deployment Options
#### Latest Version
For the most recent updates, use our latest Docker image which is automatically built nightly:
```yaml
uses: qodo-ai/pr-agent@main
```
#### Specific Release Version
For a fixed version, you can pin your action to a specific release version. Browse available releases at:
[PR-Agent Releases](https://github.com/qodo-ai/pr-agent/releases)
For example, to github action:
```yaml
steps:
- name: PR Agent action step
id: pragent
uses: docker://codiumai/pr-agent:0.26-github_action
```
#### Enhanced Security with Docker Digest
For maximum security, you can specify the Docker image using its digest:
```yaml
steps:
- name: PR Agent action step
id: pragent
uses: docker://codiumai/pr-agent@sha256:14165e525678ace7d9b51cda8652c2d74abb4e1d76b57c4a6ccaeba84663cc64
```
## Reporting a Vulnerability
We take the security of PR-Agent seriously. If you discover a security vulnerability, please report it immediately to:
Email: tal.r@qodo.ai
Please include a description of the vulnerability, steps to reproduce, and the affected PR-Agent version.

View File

@ -4,7 +4,7 @@ WORKDIR /app
ADD pyproject.toml .
ADD requirements.txt .
ADD docs docs
RUN pip install . && rm pyproject.toml requirements.txt
RUN pip install --no-cache-dir . && rm pyproject.toml requirements.txt
ENV PYTHONPATH=/app
FROM base AS github_app
@ -33,7 +33,7 @@ CMD ["python", "pr_agent/servers/azuredevops_server_webhook.py"]
FROM base AS test
ADD requirements-dev.txt .
RUN pip install -r requirements-dev.txt && rm requirements-dev.txt
RUN pip install --no-cache-dir -r requirements-dev.txt && rm requirements-dev.txt
ADD pr_agent pr_agent
ADD tests tests

View File

@ -5,8 +5,8 @@ RUN yum update -y && \
yum clean all
ADD pyproject.toml requirements.txt .
RUN pip install . && rm pyproject.toml
RUN pip install mangum==0.17.0
RUN pip install --no-cache-dir . && rm pyproject.toml
RUN pip install --no-cache-dir mangum==0.17.0
COPY pr_agent/ ${LAMBDA_TASK_ROOT}/pr_agent/
CMD ["pr_agent.servers.serverless.serverless"]

View File

@ -19,6 +19,7 @@ Here are some additional technical blogs from Qodo, that delve deeper into the c
These resources provide more comprehensive insights into leveraging LLMs for software development.
### Code Generation and LLMs
- [Effective AI code suggestions: less is more](https://www.qodo.ai/blog/effective-code-suggestions-llms-less-is-more/)
- [State-of-the-art Code Generation with AlphaCodium From Prompt Engineering to Flow Engineering](https://www.qodo.ai/blog/qodoflow-state-of-the-art-code-generation-for-code-contests/)
- [RAG for a Codebase with 10k Repos](https://www.qodo.ai/blog/rag-for-large-scale-code-repos/)

View File

@ -15,7 +15,7 @@ Qodo Merge for GitHub cloud is available for installation through the [GitHub Ma
### GitHub Enterprise Server
To use Qodo Merge application on your private GitHub Enterprise Server, you will need to contact us for starting an [Enterprise](https://www.codium.ai/pricing/) trial.
To use Qodo Merge application on your private GitHub Enterprise Server, you will need to [contact](https://www.qodo.ai/contact/#pricing) Qodo for starting an Enterprise trial.
### GitHub Open Source Projects
@ -34,7 +34,9 @@ Qodo Merge for Bitbucket Cloud is available for installation through the followi
To use Qodo Merge application on your private Bitbucket Server, you will need to contact us for starting an [Enterprise](https://www.qodo.ai/pricing/) trial.
## Install Qodo Merge for GitLab (Teams & Enterprise)
## Install Qodo Merge for GitLab
### GitLab Cloud
Since GitLab platform does not support apps, installing Qodo Merge for GitLab is a bit more involved, and requires the following steps:
@ -79,3 +81,7 @@ Enable SSL verification: Check the box.
Youre all set!
Open a new merge request or add a MR comment with one of Qodo Merges commands such as /review, /describe or /improve.
### GitLab Server
For a trial period of two weeks on your private GitLab Server, the same [installation steps](#gitlab-cloud) as for GitLab Cloud apply. After the trial period, you will need to [contact](https://www.qodo.ai/contact/#pricing) Qodo for moving to an Enterprise account.

View File

@ -1,6 +1,6 @@
### Overview
[Qodo Merge](https://www.codium.ai/pricing/){:target="_blank"} is a hosted version of open-source [PR-Agent](https://github.com/Codium-ai/pr-agent){:target="_blank"}. A complimentary two-week trial is offered, followed by a monthly subscription fee.
[Qodo Merge](https://www.codium.ai/pricing/){:target="_blank"} is a paid, hosted version of open-source [PR-Agent](https://github.com/Codium-ai/pr-agent){:target="_blank"}. A complimentary two-week trial is offered, followed by a monthly subscription fee.
Qodo Merge is designed for companies and teams that require additional features and capabilities. It provides the following benefits:
1. **Fully managed** - We take care of everything for you - hosting, models, regular updates, and more. Installation is as simple as signing up and adding the Qodo Merge app to your GitHub\GitLab\BitBucket repo.

View File

@ -85,7 +85,19 @@ publish_labels = true
</tr>
<tr>
<td><b>collapsible_file_list</b></td>
<td>If set to true, the file list in the "Changes walkthrough" section will be collapsible. If set to "adaptive", the file list will be collapsible only if there are more than 8 files. Default is "adaptive".</td>
<td>If set to true, the file list in the "Changes walkthrough" section will be collapsible. If set to "adaptive", the file list will be collapsible only if the number of files exceeds the threshold defined by `collapsible_file_list_threshold`. Default is "adaptive".</td>
</tr>
<tr>
<td><b>collapsible_file_list_threshold</b></td>
<td>The number of files threshold for when to make the file list collapsible when using 'adaptive' mode. Default is 8.</td>
</tr>
<tr>
<td><b>inline_file_summary</b></td>
<td>Controls where and how file summaries are displayed:
<br>- 'table': Displays file changes walkthrough table on both "Files changed" and "Conversation" tabs
<br>- true: Adds a collapsible file comment with changes title and summary for each file
<br>- false: Shows file changes walkthrough only in the "Conversation" tab
<br>Default is false.</td>
</tr>
<tr>
<td><b>enable_large_pr_handling</b></td>
@ -95,6 +107,14 @@ publish_labels = true
<td><b>enable_help_text</b></td>
<td>If set to true, the tool will display a help text in the comment. Default is false.</td>
</tr>
<tr>
<td><b>enable_help_comment</b></td>
<td>If set to true, the help guidance text is displayed in the comment. Default is true.</td>
</tr>
<tr>
<td><b>enable_override_title_with_parent_tag</b></td>
<td>If set to true, the tool will set the PR title to the next patch version from the latest tag in the target branch, with an RC suffix (e.g., v1.0.1-rc.1). Default is false.</td>
</tr>
</table>

View File

@ -1,3 +1,5 @@
`Platforms supported: GitHub, GitLab, Bitbucket`
## Overview
The `implement` tool converts human code review discussions and feedback into ready-to-commit code changes.

View File

@ -1,18 +0,0 @@
## Qodo Merge Models
The default models used by Qodo Merge are a combination of Claude-3.5-sonnet and OpenAI's GPT-4 models.
Users can configure Qodo Merge to use solely a specific model by editing the [configuration](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/) file.
For example, to restrict Qodo Merge to using only `Claude-3.5-sonnet`, add this setting:
```
[config]
model="claude-3-5-sonnet"
```
Or to restrict Qodo Merge to using only `GPT-4o`, add this setting:
```
[config]
model="gpt-4o"
```

View File

@ -51,7 +51,7 @@ api_base = "http://localhost:11434" # or whatever port you're running Ollama on
Commercial models such as GPT-4, Claude Sonnet, and Gemini have demonstrated robust capabilities in generating structured output for code analysis tasks with large input. In contrast, most open-source models currently available (as of January 2025) face challenges with these complex tasks.
Based on our testing, local open-source models are suitable for experimentation and learning purposes, but they are not suitable for production-level code analysis tasks.
Based on our testing, local open-source models are suitable for experimentation and learning purposes (mainly for the `ask` command), but they are not suitable for production-level code analysis tasks.
Hence, for production workflows and real-world usage, we recommend using commercial models.

View File

@ -24,4 +24,4 @@ It includes information on how to adjust Qodo Merge configurations, define which
- [Changing a model](./additional_configurations.md#changing-a-model)
- [Patch Extra Lines](./additional_configurations.md#patch-extra-lines)
- [Editing the prompts](./additional_configurations.md#editing-the-prompts)
- [Qodo Merge Models](./PR_agent_pro_models.md)
- [Qodo Merge Models](./qodo_merge_models)

View File

@ -0,0 +1,37 @@
The default models used by Qodo Merge are a combination of Claude-3.5-sonnet and OpenAI's GPT-4 models.
### Selecting a Specific Model
Users can configure Qodo Merge to use a specific model by editing the [configuration](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/) file.
The models supported by Qodo Merge are:
- `claude-3-5-sonnet`
- `gpt-4o`
- `deepseek-r1`
- `o3-mini`
To restrict Qodo Merge to using only `Claude-3.5-sonnet`, add this setting:
```
[config]
model="claude-3-5-sonnet"
```
To restrict Qodo Merge to using only `GPT-4o`, add this setting:
```
[config]
model="gpt-4o"
```
To restrict Qodo Merge to using only `deepseek-r1`, add this setting:
```
[config]
model="deepseek/r1"
```
To restrict Qodo Merge to using only `o3-mini`, add this setting:
```
[config]
model="o3-mini"
```

View File

@ -20,7 +20,7 @@ nav:
- Managing Mail Notifications: 'usage-guide/mail_notifications.md'
- Changing a Model: 'usage-guide/changing_a_model.md'
- Additional Configurations: 'usage-guide/additional_configurations.md'
- 💎 Qodo Merge Models: 'usage-guide/PR_agent_pro_models'
- 💎 Qodo Merge Models: 'usage-guide/qodo_merge_models.md'
- Tools:
- 'tools/index.md'
- Describe: 'tools/describe.md'

View File

@ -26,6 +26,8 @@ MAX_TOKENS = {
'o1-preview-2024-09-12': 128000, # 128K, but may be limited by config.max_model_tokens
'o1-2024-12-17': 204800, # 200K, but may be limited by config.max_model_tokens
'o1': 204800, # 200K, but may be limited by config.max_model_tokens
'o3-mini': 204800, # 200K, but may be limited by config.max_model_tokens
'o3-mini-2025-01-31': 204800, # 200K, but may be limited by config.max_model_tokens
'claude-instant-1': 100000,
'claude-2': 100000,
'command-nightly': 4096,
@ -81,3 +83,13 @@ MAX_TOKENS = {
"watsonx/ibm/granite-34b-code-instruct": 8191,
"watsonx/mistralai/mistral-large": 32768,
}
USER_MESSAGE_ONLY_MODELS = [
"deepseek/deepseek-reasoner",
"o1-mini",
"o1-mini-2024-09-12",
"o1",
"o1-2024-12-17",
"o3-mini",
"o3-mini-2025-01-31"
]

View File

@ -6,6 +6,7 @@ import requests
from litellm import acompletion
from tenacity import retry, retry_if_exception_type, stop_after_attempt
from pr_agent.algo import USER_MESSAGE_ONLY_MODELS
from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler
from pr_agent.algo.utils import get_version
from pr_agent.config_loader import get_settings
@ -94,6 +95,9 @@ class LiteLLMAIHandler(BaseAiHandler):
if get_settings().get("DEEPSEEK.KEY", None):
os.environ['DEEPSEEK_API_KEY'] = get_settings().get("DEEPSEEK.KEY")
# Models that only use user meessage
self.user_message_only_models = USER_MESSAGE_ONLY_MODELS
def prepare_logs(self, response, system, user, resp, finish_reason):
response_log = response.dict().copy()
response_log['system'] = system
@ -197,10 +201,8 @@ class LiteLLMAIHandler(BaseAiHandler):
messages[1]["content"] = [{"type": "text", "text": messages[1]["content"]},
{"type": "image_url", "image_url": {"url": img_path}}]
# Currently, model OpenAI o1 series does not support a separate system and user prompts
O1_MODEL_PREFIX = 'o1'
model_type = model.split('/')[-1] if '/' in model else model
if (model_type.startswith(O1_MODEL_PREFIX)) or ("deepseek-reasoner" in model):
# Currently, some models do not support a separate system and user prompts
if self.user_message_only_models and any(entry.lower() in model.lower() for entry in self.user_message_only_models):
user = f"{system}\n\n\n{user}"
system = ""
get_logger().info(f"Using model {model}, combining system and user prompts")

View File

@ -735,7 +735,7 @@ def try_fix_yaml(response_text: str,
get_logger().info(f"Successfully parsed AI prediction after adding |-\n")
return data
except:
get_logger().info(f"Failed to parse AI prediction after adding |-\n")
pass
# second fallback - try to extract only range from first ```yaml to ````
snippet_pattern = r'```(yaml)?[\s\S]*?```'
@ -779,9 +779,18 @@ def try_fix_yaml(response_text: str,
except:
pass
# fifth fallback - try to remove leading '+' (sometimes added by AI for 'existing code' and 'improved code')
response_text_lines_copy = response_text_lines.copy()
for i in range(0, len(response_text_lines_copy)):
response_text_lines_copy[i] = ' ' + response_text_lines_copy[i][1:]
try:
data = yaml.safe_load('\n'.join(response_text_lines_copy))
get_logger().info(f"Successfully parsed AI prediction after removing leading '+'")
return data
except:
pass
# fifth fallback - try to remove last lines
data = {}
# sixth fallback - try to remove last lines
for i in range(1, len(response_text_lines)):
response_text_lines_tmp = '\n'.join(response_text_lines[:-i])
try:

View File

@ -9,7 +9,7 @@ from datetime import datetime
from typing import Optional, Tuple
from urllib.parse import urlparse
from github import AppAuthentication, Auth, Github
from github import AppAuthentication, Auth, Github, GithubException
from retry import retry
from starlette_context import context
@ -475,8 +475,17 @@ class GithubProvider(GitProvider):
return False
def edit_comment(self, comment, body: str):
body = self.limit_output_characters(body, self.max_comment_chars)
comment.edit(body=body)
try:
body = self.limit_output_characters(body, self.max_comment_chars)
comment.edit(body=body)
except GithubException as e:
if hasattr(e, "status") and e.status == 403:
# Log as warning for permission-related issues (usually due to polling)
get_logger().warning(
"Failed to edit github comment due to permission restrictions",
artifact={"error": e})
else:
get_logger().exception(f"Failed to edit github comment", artifact={"error": e})
def edit_comment_from_comment_id(self, comment_id: int, body: str):
try:

View File

@ -81,7 +81,7 @@ async def run_action():
get_logger().info(f"github action: failed to apply repo settings: {e}")
# Handle pull request opened event
if GITHUB_EVENT_NAME == "pull_request":
if GITHUB_EVENT_NAME == "pull_request" or GITHUB_EVENT_NAME == "pull_request_target":
action = event_payload.get("action")
# Retrieve the list of actions from the configuration

View File

@ -130,12 +130,14 @@ async def is_valid_notification(notification, headers, handled_ids, session, use
artifact={"comment": comment_body})
return True, handled_ids, comment, comment_body, pr_url, user_tag
get_logger().error(f"Failed to fetch comments for PR: {pr_url}")
get_logger().warning(f"Failed to fetch comments for PR: {pr_url}",
artifact={"comments": comments})
return False, handled_ids
return False, handled_ids
except Exception as e:
get_logger().error(f"Error processing notification: {e}", artifact={"traceback": traceback.format_exc()})
get_logger().exception(f"Error processing polling notification",
artifact={"notification": notification, "error": e})
return False, handled_ids

View File

@ -121,6 +121,9 @@ max_history_len=4
apply_suggestions_checkbox=true
# suggestions scoring
suggestions_score_threshold=0 # [0-10]| recommend not to set this value above 8, since above it may clip highly relevant suggestions
new_score_mechanism=true
new_score_mechanism_th_high=9
new_score_mechanism_th_medium=7
# params for '/improve --extended' mode
auto_extended_mode=true
num_code_suggestions_per_chunk=4

View File

@ -90,7 +90,7 @@ class CodeSuggestion(BaseModel):
{%- if not focus_only_on_problems %}
label: str = Field(description="A single, descriptive label that best characterizes the suggestion type. Possible labels include 'security', 'possible bug', 'possible issue', 'performance', 'enhancement', 'best practice', 'maintainability', 'typo'. Other relevant labels are also acceptable.")
{%- else %}
label: str = Field(description="A single, descriptive label that best characterizes the suggestion type. Possible labels include 'security', 'critical bug', 'general'. The 'general' section should be used for suggestions that address a major issue, but are necessarily on a critical level.")
label: str = Field(description="A single, descriptive label that best characterizes the suggestion type. Possible labels include 'security', 'critical bug', 'general'. The 'general' section should be used for suggestions that address a major issue, but are not necessarily on a critical level.")
{%- endif %}

View File

@ -13,7 +13,7 @@ The output must be a YAML object equivalent to type $DocHelper, according to the
=====
class relevant_section(BaseModel):
file_name: str = Field(description="The name of the relevant file")
relevant_section_header_string: str = Field(description="From the relevant file, exact text of the relevant section heading. If no markdown heading is relevant, return empty string")
relevant_section_header_string: str = Field(description="The exact text of the relevant markdown section heading from the relevant file (starting with '#', '##', etc.). Return empty string if the entire file is the relevant section, or if the relevant section has no heading")
class DocHelper(BaseModel):
user_question: str = Field(description="The user's question")

View File

@ -720,7 +720,7 @@ class PRCodeSuggestions:
header = f"Suggestion"
delta = 66
header += "&nbsp; " * delta
pr_body += f"""<thead><tr><td>Category</td><td align=left>{header}</td><td align=center>Score</td></tr>"""
pr_body += f"""<thead><tr><td><strong>Category</strong></td><td align=left><strong>{header}</strong></td><td align=center><strong>Impact</strong></td></tr>"""
pr_body += """<tbody>"""
suggestions_labels = dict()
# add all suggestions related to each label
@ -740,7 +740,7 @@ class PRCodeSuggestions:
counter_suggestions = 0
for label, suggestions in suggestions_labels.items():
num_suggestions = len(suggestions)
pr_body += f"""<tr><td rowspan={num_suggestions}><strong>{label.capitalize()}</strong></td>\n"""
pr_body += f"""<tr><td rowspan={num_suggestions}>{label.capitalize()}</td>\n"""
for i, suggestion in enumerate(suggestions):
relevant_file = suggestion['relevant_file'].strip()
@ -794,14 +794,19 @@ class PRCodeSuggestions:
{example_code.rstrip()}
"""
pr_body += f"<details><summary>Suggestion importance[1-10]: {suggestion['score']}</summary>\n\n"
pr_body += f"Why: {suggestion['score_why']}\n\n"
pr_body += f"</details>"
if suggestion.get('score_why'):
pr_body += f"<details><summary>Suggestion importance[1-10]: {suggestion['score']}</summary>\n\n"
pr_body += f"__\n\nWhy: {suggestion['score_why']}\n\n"
pr_body += f"</details>"
pr_body += f"</details>"
# # add another column for 'score'
pr_body += f"</td><td align=center>{suggestion['score']}\n\n"
score_int = int(suggestion.get('score', 0))
score_str = f"{score_int}"
if get_settings().pr_code_suggestions.new_score_mechanism:
score_str = self.get_score_str(score_int)
pr_body += f"</td><td align=center>{score_str}\n\n"
pr_body += f"</td></tr>"
counter_suggestions += 1
@ -814,6 +819,16 @@ class PRCodeSuggestions:
get_logger().info(f"Failed to publish summarized code suggestions, error: {e}")
return ""
def get_score_str(self, score: int) -> str:
th_high = get_settings().pr_code_suggestions.get('new_score_mechanism_th_high', 9)
th_medium = get_settings().pr_code_suggestions.get('new_score_mechanism_th_medium', 7)
if score >= th_high:
return "High"
elif score >= th_medium:
return "Medium"
else: # score < 7
return "Low"
async def self_reflect_on_suggestions(self,
suggestion_list: List,
patches_diff: str,

View File

@ -1,4 +1,5 @@
import copy
import re
from functools import partial
from pathlib import Path
@ -9,10 +10,9 @@ from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler
from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler
from pr_agent.algo.pr_processing import retry_with_fallback_models
from pr_agent.algo.token_handler import TokenHandler
from pr_agent.algo.utils import ModelType, clip_tokens, load_yaml
from pr_agent.algo.utils import ModelType, clip_tokens, load_yaml, get_max_tokens
from pr_agent.config_loader import get_settings
from pr_agent.git_providers import (BitbucketServerProvider, GithubProvider,
get_git_provider_with_context)
from pr_agent.git_providers import BitbucketServerProvider, GithubProvider, get_git_provider_with_context
from pr_agent.log import get_logger
@ -30,10 +30,11 @@ def extract_header(snippet):
return res
class PRHelpMessage:
def __init__(self, pr_url: str, args=None, ai_handler: partial[BaseAiHandler,] = LiteLLMAIHandler):
def __init__(self, pr_url: str, args=None, ai_handler: partial[BaseAiHandler,] = LiteLLMAIHandler, return_as_string=False):
self.git_provider = get_git_provider_with_context(pr_url)
self.ai_handler = ai_handler()
self.question_str = self.parse_args(args)
self.return_as_string = return_as_string
self.num_retrieved_snippets = get_settings().get('pr_help.num_retrieved_snippets', 5)
if self.question_str:
self.vars = {
@ -65,6 +66,34 @@ class PRHelpMessage:
question_str = ""
return question_str
def format_markdown_header(self, header: str) -> str:
try:
# First, strip common characters from both ends
cleaned = header.strip('# 💎\n')
# Define all characters to be removed/replaced in a single pass
replacements = {
"'": '',
"`": '',
'(': '',
')': '',
',': '',
'.': '',
'?': '',
'!': '',
' ': '-'
}
# Compile regex pattern for characters to remove
pattern = re.compile('|'.join(map(re.escape, replacements.keys())))
# Perform replacements in a single pass and convert to lowercase
return pattern.sub(lambda m: replacements[m.group()], cleaned).lower()
except Exception:
get_logger().exception(f"Error while formatting markdown header", artifacts={'header': header})
return ""
async def run(self):
try:
if self.question_str:
@ -106,7 +135,10 @@ class PRHelpMessage:
get_logger().debug(f"Token count of full documentation website: {token_count}")
model = get_settings().config.model
max_tokens_full = MAX_TOKENS[model] # note - here we take the actual max tokens, without any reductions. we do aim to get the full documentation website in the prompt
if model in MAX_TOKENS:
max_tokens_full = MAX_TOKENS[model] # note - here we take the actual max tokens, without any reductions. we do aim to get the full documentation website in the prompt
else:
max_tokens_full = get_max_tokens(model)
delta_output = 2000
if token_count > max_tokens_full - delta_output:
get_logger().info(f"Token count {token_count} exceeds the limit {max_tokens_full - delta_output}. Skipping the PR Help message.")
@ -114,8 +146,16 @@ class PRHelpMessage:
self.vars['snippets'] = docs_prompt.strip()
# run the AI model
response = await retry_with_fallback_models(self._prepare_prediction, model_type=ModelType.WEAK)
response = await retry_with_fallback_models(self._prepare_prediction, model_type=ModelType.REGULAR)
response_yaml = load_yaml(response)
if isinstance(response_yaml, str):
get_logger().warning(f"failing to parse response: {response_yaml}, publishing the response as is")
if get_settings().config.publish_output:
answer_str = f"### Question: \n{self.question_str}\n\n"
answer_str += f"### Answer:\n\n"
answer_str += response_yaml
self.git_provider.publish_comment(answer_str)
return ""
response_str = response_yaml.get('response')
relevant_sections = response_yaml.get('relevant_sections')
@ -138,7 +178,7 @@ class PRHelpMessage:
for section in relevant_sections:
file = section.get('file_name').strip().removesuffix('.md')
if str(section['relevant_section_header_string']).strip():
markdown_header = section['relevant_section_header_string'].strip().strip('#').strip().lower().replace(' ', '-').replace("'", '').replace('(', '').replace(')', '').replace(',', '').replace('.', '').replace('?', '').replace('!', '')
markdown_header = self.format_markdown_header(section['relevant_section_header_string'])
answer_str += f"> - {base_path}{file}#{markdown_header}\n"
else:
answer_str += f"> - {base_path}{file}\n"

View File

@ -371,7 +371,7 @@ class PRReviewer:
else:
get_logger().warning(f"Unexpected type for estimated_effort: {type(estimated_effort)}")
if 1 <= estimated_effort_number <= 5: # 1, because ...
review_labels.append(f'Review effort [1-5]: {estimated_effort_number}')
review_labels.append(f'Review effort {estimated_effort_number}/5')
if get_settings().pr_reviewer.enable_review_labels_security and get_settings().pr_reviewer.require_security_review:
security_concerns = data['review']['security_concerns'] # yes, because ...
security_concerns_bool = 'yes' in security_concerns.lower() or 'true' in security_concerns.lower()

View File

@ -3,4 +3,3 @@
from setuptools import setup
setup()
print("aaa")