mirror of
https://github.com/qodo-ai/pr-agent.git
synced 2025-07-08 14:50:40 +08:00
Merge commit 'a134a8bf6d44de526d6fcbba13c1f9813a5dea09' into hl/flip_2_configs
# Conflicts: # pr_agent/settings/configuration.toml
This commit is contained in:
76
README.md
76
README.md
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
</picture>
|
</picture>
|
||||||
<br/>
|
<br/>
|
||||||
Making pull requests less painful with an AI agent
|
CodiumAI PR-Agent aims to help efficiently review and handle pull requests, by providing AI feedbacks and suggestions
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
[](https://github.com/Codium-ai/pr-agent/blob/main/LICENSE)
|
[](https://github.com/Codium-ai/pr-agent/blob/main/LICENSE)
|
||||||
@ -21,18 +21,31 @@ Making pull requests less painful with an AI agent
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
### [Documentation](https://pr-agent-docs.codium.ai/)
|
||||||
|
- See the [Installation Guide](https://pr-agent-docs.codium.ai/installation/) for instructions on installing PR-Agent on different platforms.
|
||||||
|
|
||||||
|
- See the [Usage Guide](https://pr-agent-docs.codium.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 [Tools Guide](https://pr-agent-docs.codium.ai/tools/) for a detailed description of the different tools, and the available configurations for each tool.
|
||||||
|
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
- [News and Updates](#news-and-updates)
|
- [News and Updates](#news-and-updates)
|
||||||
- [Overview](#overview)
|
- [Overview](#overview)
|
||||||
- [Example results](#example-results)
|
- [Example results](#example-results)
|
||||||
- [Try it now](#try-it-now)
|
- [Try it now](#try-it-now)
|
||||||
- [Installation](#installation)
|
|
||||||
- [PR-Agent Pro 💎](#pr-agent-pro-)
|
- [PR-Agent Pro 💎](#pr-agent-pro-)
|
||||||
- [How it works](#how-it-works)
|
- [How it works](#how-it-works)
|
||||||
- [Why use PR-Agent?](#why-use-pr-agent)
|
- [Why use PR-Agent?](#why-use-pr-agent)
|
||||||
|
|
||||||
## News and Updates
|
## News and Updates
|
||||||
|
|
||||||
|
### April 14, 2024
|
||||||
|
You can now ask questions about images that appear in the comment, where the entire PR is considered as the context.
|
||||||
|
see [here](https://pr-agent-docs.codium.ai/tools/ask/#ask-on-images) for more details.
|
||||||
|
|
||||||
|
<kbd><img src="https://codium.ai/images/pr_agent/ask_images5.png" width="512"></kbd>
|
||||||
|
|
||||||
### March 24, 2024
|
### March 24, 2024
|
||||||
PR-Agent is now available for easy installation via [pip](https://pr-agent-docs.codium.ai/installation/locally/#using-pip-package).
|
PR-Agent is now available for easy installation via [pip](https://pr-agent-docs.codium.ai/installation/locally/#using-pip-package).
|
||||||
|
|
||||||
@ -63,14 +76,6 @@ If set to true, the tool will add a section that checks if the PR contains sever
|
|||||||
## Overview
|
## Overview
|
||||||
<div style="text-align:left;">
|
<div style="text-align:left;">
|
||||||
|
|
||||||
CodiumAI PR-Agent aims to help efficiently review and handle pull requests, by providing AI feedbacks and suggestions
|
|
||||||
|
|
||||||
- See the [Installation Guide](https://pr-agent-docs.codium.ai/installation/) for instructions on installing and running the tool on different git platforms.
|
|
||||||
|
|
||||||
- See the [Usage Guide](https://pr-agent-docs.codium.ai/usage-guide/) for instructions on running the PR-Agent commands via different interfaces, including _CLI_, _online usage_, or by _automatically triggering_ them when a new PR is opened.
|
|
||||||
|
|
||||||
- See the [Tools Guide](https://pr-agent-docs.codium.ai/tools/) for a detailed description of the different tools.
|
|
||||||
|
|
||||||
Supported commands per platform:
|
Supported commands per platform:
|
||||||
|
|
||||||
| | | GitHub | Gitlab | Bitbucket | Azure DevOps |
|
| | | GitHub | Gitlab | Bitbucket | Azure DevOps |
|
||||||
@ -136,7 +141,7 @@ ___
|
|||||||
\
|
\
|
||||||
‣ **CI Feedback 💎 ([`/checks ci_job`](https://pr-agent-docs.codium.ai/tools/ci_feedback/))**: Automatically generates feedback and analysis for a failed CI job.
|
‣ **CI Feedback 💎 ([`/checks ci_job`](https://pr-agent-docs.codium.ai/tools/ci_feedback/))**: Automatically generates feedback and analysis for a failed CI job.
|
||||||
\
|
\
|
||||||
‣ **Similar Code 💎 ([`/find_similar_component`](https://pr-agent-docs.codium.ai/tools/similar_code//))**: Retrieves the most similar code components from inside the organization's codebase, or from open-source code.
|
‣ **Similar Code 💎 ([`/find_similar_component`](https://pr-agent-docs.codium.ai/tools/similar_code/))**: Retrieves the most similar code components from inside the organization's codebase, or from open-source code.
|
||||||
___
|
___
|
||||||
|
|
||||||
## Example results
|
## Example results
|
||||||
@ -235,32 +240,47 @@ Note that when you set your own PR-Agent or use CodiumAI hosted PR-Agent, there
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Installation
|
[//]: # (## Installation)
|
||||||
To use your own version of PR-Agent, you first need to acquire two tokens:
|
|
||||||
|
|
||||||
1. An OpenAI key from [here](https://platform.openai.com/), with access to GPT-4.
|
[//]: # (To use your own version of PR-Agent, you first need to acquire two tokens:)
|
||||||
2. A GitHub personal access token (classic) with the repo scope.
|
|
||||||
|
|
||||||
There are several ways to use PR-Agent:
|
[//]: # ()
|
||||||
|
[//]: # (1. An OpenAI key from [here](https://platform.openai.com/), with access to GPT-4.)
|
||||||
|
|
||||||
**Locally**
|
[//]: # (2. A GitHub personal access token (classic) with the repo scope.)
|
||||||
- [Using pip package](https://pr-agent-docs.codium.ai/installation/locally/#using-pip-package)
|
|
||||||
- [Using Docker image](https://pr-agent-docs.codium.ai/installation/locally/#using-docker-image)
|
|
||||||
- [Run from source](https://pr-agent-docs.codium.ai/installation/locally/#run-from-source)
|
|
||||||
|
|
||||||
**GitHub specific methods**
|
[//]: # ()
|
||||||
- [Run as a GitHub Action](https://pr-agent-docs.codium.ai/installation/github/#run-as-a-github-action)
|
[//]: # (There are several ways to use PR-Agent:)
|
||||||
- [Run as a GitHub App](https://pr-agent-docs.codium.ai/installation/github/#run-as-a-github-app)
|
|
||||||
|
|
||||||
**GitLab specific methods**
|
[//]: # ()
|
||||||
- [Run a GitLab webhook server](https://pr-agent-docs.codium.ai/installation/gitlab/)
|
[//]: # (**Locally**)
|
||||||
|
|
||||||
**BitBucket specific methods**
|
[//]: # (- [Using pip package](https://pr-agent-docs.codium.ai/installation/locally/#using-pip-package))
|
||||||
- [Run as a Bitbucket Pipeline](https://pr-agent-docs.codium.ai/installation/bitbucket/)
|
|
||||||
|
[//]: # (- [Using Docker image](https://pr-agent-docs.codium.ai/installation/locally/#using-docker-image))
|
||||||
|
|
||||||
|
[//]: # (- [Run from source](https://pr-agent-docs.codium.ai/installation/locally/#run-from-source))
|
||||||
|
|
||||||
|
[//]: # ()
|
||||||
|
[//]: # (**GitHub specific methods**)
|
||||||
|
|
||||||
|
[//]: # (- [Run as a GitHub Action](https://pr-agent-docs.codium.ai/installation/github/#run-as-a-github-action))
|
||||||
|
|
||||||
|
[//]: # (- [Run as a GitHub App](https://pr-agent-docs.codium.ai/installation/github/#run-as-a-github-app))
|
||||||
|
|
||||||
|
[//]: # ()
|
||||||
|
[//]: # (**GitLab specific methods**)
|
||||||
|
|
||||||
|
[//]: # (- [Run a GitLab webhook server](https://pr-agent-docs.codium.ai/installation/gitlab/))
|
||||||
|
|
||||||
|
[//]: # ()
|
||||||
|
[//]: # (**BitBucket specific methods**)
|
||||||
|
|
||||||
|
[//]: # (- [Run as a Bitbucket Pipeline](https://pr-agent-docs.codium.ai/installation/bitbucket/))
|
||||||
|
|
||||||
## PR-Agent Pro 💎
|
## PR-Agent Pro 💎
|
||||||
[PR-Agent Pro](https://www.codium.ai/pricing/) is a hosted version of PR-Agent, provided by CodiumAI. It is available for a monthly fee, and provides the following benefits:
|
[PR-Agent Pro](https://www.codium.ai/pricing/) is a hosted version of PR-Agent, provided by CodiumAI. It is available for a monthly fee, and 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 PR-Agent app to your GitHub\BitBucket repo.
|
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 PR-Agent app to your GitHub\GitLab\BitBucket repo.
|
||||||
2. **Improved privacy** - No data will be stored or used to train models. PR-Agent Pro will employ zero data retention, and will use an OpenAI account with zero data retention.
|
2. **Improved privacy** - No data will be stored or used to train models. PR-Agent Pro will employ zero data retention, and will use an OpenAI account with zero data retention.
|
||||||
3. **Improved support** - PR-Agent Pro users will receive priority support, and will be able to request new features and capabilities.
|
3. **Improved support** - PR-Agent Pro users will receive priority support, and will be able to request new features and capabilities.
|
||||||
4. **Extra features** -In addition to the benefits listed above, PR-Agent Pro will emphasize more customization, and the usage of static code analysis, in addition to LLM logic, to improve results.
|
4. **Extra features** -In addition to the benefits listed above, PR-Agent Pro will emphasize more customization, and the usage of static code analysis, in addition to LLM logic, to improve results.
|
||||||
|
@ -1,15 +1 @@
|
|||||||
# To install:
|
# [Visit Our Docs Portal](https://pr-agent-docs.codium.ai/)
|
||||||
pip install mkdocs
|
|
||||||
pip install mkdocs-material
|
|
||||||
pip install mkdocs-material-extensions
|
|
||||||
pip install "mkdocs-material[imaging]"
|
|
||||||
|
|
||||||
# docs
|
|
||||||
To run localy: `mkdocs serve`
|
|
||||||
|
|
||||||
To expand and customize the theme: [Material MKDocs](https://squidfunk.github.io/mkdocs-material/)
|
|
||||||
|
|
||||||
The deployment is managed on the gh-pages branches.
|
|
||||||
After each merge to main the deplloyment will be taken care of by GH action automatically and the new version will be available at: [Docs](https://codium-ai.github.io/docs/)
|
|
||||||
|
|
||||||
Github action is located in `.github/workflows/ci.yml` file.
|
|
||||||
|
@ -19,20 +19,19 @@ PR-Agent offers extensive pull request functionalities across various git provid
|
|||||||
| | ⮑ [SOC2 Compliance](https://pr-agent-docs.codium.ai/tools/review/#soc2-ticket-compliance){:target="_blank"} 💎 | ✅ | ✅ | ✅ | ✅ |
|
| | ⮑ [SOC2 Compliance](https://pr-agent-docs.codium.ai/tools/review/#soc2-ticket-compliance){:target="_blank"} 💎 | ✅ | ✅ | ✅ | ✅ |
|
||||||
| | Ask | ✅ | ✅ | ✅ | ✅ |
|
| | Ask | ✅ | ✅ | ✅ | ✅ |
|
||||||
| | Describe | ✅ | ✅ | ✅ | ✅ |
|
| | Describe | ✅ | ✅ | ✅ | ✅ |
|
||||||
| | ⮑ [Inline file summary](https://pr-agent-docs.codium.ai/tools/describe/#inline-file-summary){:target="_blank"} 💎 | ✅ | ✅ | ✅ | ✅ |
|
| | ⮑ [Inline file summary](https://pr-agent-docs.codium.ai/tools/describe/#inline-file-summary){:target="_blank"} 💎 | ✅ | ✅ | | ✅ |
|
||||||
| | Improve | ✅ | ✅ | ✅ | ✅ |
|
| | Improve | ✅ | ✅ | ✅ | ✅ |
|
||||||
| | ⮑ Extended | ✅ | ✅ | ✅ | ✅ |
|
| | ⮑ Extended | ✅ | ✅ | ✅ | ✅ |
|
||||||
| | [Custom Suggestions](./tools/custom_suggestions.md){:target="_blank"} 💎 | ✅ | ✅ | ✅ | ✅ |
|
| | [Custom Suggestions](./tools/custom_suggestions.md){:target="_blank"} 💎 | ✅ | ✅ | ✅ | ✅ |
|
||||||
| | Reflect and Review | ✅ | ✅ | ✅ | ✅ |
|
| | Reflect and Review | ✅ | ✅ | ✅ | ✅ |
|
||||||
| | Update CHANGELOG.md | ✅ | ✅ | ✅ | ️ |
|
| | Update CHANGELOG.md | ✅ | ✅ | ✅ | ️ |
|
||||||
| | Find Similar Issue | ✅ | | | ️ |
|
| | Find Similar Issue | ✅ | | | ️ |
|
||||||
| | [Add PR Documentation](./tools/documentation.md){:target="_blank"} 💎 | ✅ | ✅ | ✅ | ✅ |
|
| | [Add PR Documentation](./tools/documentation.md){:target="_blank"} 💎 | ✅ | ✅ | | ✅ |
|
||||||
| | [Generate Custom Labels](./tools/describe.md#handle-custom-labels-from-the-repos-labels-page-💎){:target="_blank"} 💎 | ✅ | ✅ | | ✅ |
|
| | [Generate Custom Labels](./tools/describe.md#handle-custom-labels-from-the-repos-labels-page-💎){:target="_blank"} 💎 | ✅ | ✅ | | ✅ |
|
||||||
| | [Analyze PR Components](./tools/analyze.md){:target="_blank"} 💎 | ✅ | ✅ | ✅ | ✅ |
|
| | [Analyze PR Components](./tools/analyze.md){:target="_blank"} 💎 | ✅ | ✅ | | ✅ |
|
||||||
| | | | | | ️ |
|
| | | | | | ️ |
|
||||||
| USAGE | CLI | ✅ | ✅ | ✅ | ✅ |
|
| USAGE | CLI | ✅ | ✅ | ✅ | ✅ |
|
||||||
| | App / webhook | ✅ | ✅ | | ✅ |
|
| | App / webhook | ✅ | ✅ | ✅ | ✅ |
|
||||||
| | Tagging bot | ✅ | | | ✅ |
|
|
||||||
| | Actions | ✅ | | | ️ |
|
| | Actions | ✅ | | | ️ |
|
||||||
| | | | | |
|
| | | | | |
|
||||||
| CORE | PR compression | ✅ | ✅ | ✅ | ✅ |
|
| CORE | PR compression | ✅ | ✅ | ✅ | ✅ |
|
||||||
@ -46,28 +45,34 @@ PR-Agent offers extensive pull request functionalities across various git provid
|
|||||||
💎 marks a feature available only in [PR-Agent Pro](https://www.codium.ai/pricing/){:target="_blank"}
|
💎 marks a feature available only in [PR-Agent Pro](https://www.codium.ai/pricing/){:target="_blank"}
|
||||||
|
|
||||||
|
|
||||||
## Example results
|
## Example Results
|
||||||
|
<hr>
|
||||||
|
|
||||||
#### [/describe](https://github.com/Codium-ai/pr-agent/pull/530)
|
#### [/describe](https://github.com/Codium-ai/pr-agent/pull/530)
|
||||||
<figure markdown="1">
|
<figure markdown="1">
|
||||||
{width=512}
|
{width=512}
|
||||||
</figure>
|
</figure>
|
||||||
|
<hr>
|
||||||
|
|
||||||
#### [/review](https://github.com/Codium-ai/pr-agent/pull/732#issuecomment-1975099151)
|
#### [/review](https://github.com/Codium-ai/pr-agent/pull/732#issuecomment-1975099151)
|
||||||
<figure markdown="1">
|
<figure markdown="1">
|
||||||
{width=512}
|
{width=512}
|
||||||
</figure>
|
</figure>
|
||||||
|
<hr>
|
||||||
|
|
||||||
#### [/improve](https://github.com/Codium-ai/pr-agent/pull/732#issuecomment-1975099159)
|
#### [/improve](https://github.com/Codium-ai/pr-agent/pull/732#issuecomment-1975099159)
|
||||||
<figure markdown="1">
|
<figure markdown="1">
|
||||||
{width=512}
|
{width=512}
|
||||||
</figure>
|
</figure>
|
||||||
|
<hr>
|
||||||
|
|
||||||
#### [/generate_labels](https://github.com/Codium-ai/pr-agent/pull/530)
|
#### [/generate_labels](https://github.com/Codium-ai/pr-agent/pull/530)
|
||||||
<figure markdown="1">
|
<figure markdown="1">
|
||||||
{width=300}
|
{width=300}
|
||||||
</figure>
|
</figure>
|
||||||
|
<hr>
|
||||||
|
|
||||||
## How it works
|
## How it Works
|
||||||
|
|
||||||
The following diagram illustrates PR-Agent tools and their flow:
|
The following diagram illustrates PR-Agent tools and their flow:
|
||||||
|
|
||||||
@ -81,21 +86,25 @@ Check out the [PR Compression strategy](core-abilities/index.md) page for more d
|
|||||||
|
|
||||||
[PR-Agent Pro](https://www.codium.ai/pricing/) is a hosted version of PR-Agent, provided by CodiumAI. It is available for a monthly fee, and provides the following benefits:
|
[PR-Agent Pro](https://www.codium.ai/pricing/) is a hosted version of PR-Agent, provided by CodiumAI. It is available for a monthly fee, and 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 PR-Agent app to your GitHub\BitBucket repo.
|
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 PR-Agent app to your GitHub\GitLab\BitBucket repo.
|
||||||
2. **Improved privacy** - No data will be stored or used to train models. PR-Agent Pro will employ zero data retention, and will use an OpenAI account with zero data retention.
|
2. **Improved privacy** - No data will be stored or used to train models. PR-Agent Pro will employ zero data retention, and will use an OpenAI account with zero data retention.
|
||||||
3. **Improved support** - PR-Agent Pro users will receive priority support, and will be able to request new features and capabilities.
|
3. **Improved support** - PR-Agent Pro users will receive priority support, and will be able to request new features and capabilities.
|
||||||
4. **Extra features** -In addition to the benefits listed above, PR-Agent Pro will emphasize more customization, and the usage of static code analysis, in addition to LLM logic, to improve results. It has the following additional tools and features:
|
4. **Extra features** -In addition to the benefits listed above, PR-Agent Pro will emphasize more customization, and the usage of static code analysis, in addition to LLM logic, to improve results. It has the following additional tools and features:
|
||||||
- [**Analyze PR components**](./tools/analyze.md/)
|
- (Tool): [**Analyze PR components**](./tools/analyze.md/)
|
||||||
- [**Custom Code Suggestions**](./tools/custom_suggestions.md/)
|
- (Tool): [**Custom Code Suggestions**](./tools/custom_suggestions.md/)
|
||||||
- [**Tests**](./tools/test.md/)
|
- (Tool): [**Tests**](./tools/test.md/)
|
||||||
- [**PR documentation**](./tools/documentation.md/)
|
- (Tool): [**PR documentation**](./tools/documentation.md/)
|
||||||
- [**CI feedback**](./tools/ci_feedback.md/)
|
- (Tool): [**Improve Component**](https://pr-agent-docs.codium.ai/tools/improve_component/)
|
||||||
- [**SOC2 compliance check**](./tools/review.md/#soc2-ticket-compliance)
|
- (Tool): [**Similar code search**](https://pr-agent-docs.codium.ai/tools/similar_code/)
|
||||||
- [**Custom labels**](./tools/describe.md/#handle-custom-labels-from-the-repos-labels-page)
|
- (Tool): [**CI feedback**](./tools/ci_feedback.md/)
|
||||||
- [**Global and wiki configuration**](./usage-guide/configuration_options.md/#wiki-configuration-file)
|
- (Feature): [**Interactive triggering**](./usage-guide/automations_and_usage.md/#interactive-triggering)
|
||||||
|
- (Feature): [**SOC2 compliance check**](./tools/review.md/#soc2-ticket-compliance)
|
||||||
|
- (Feature): [**Custom labels**](./tools/describe.md/#handle-custom-labels-from-the-repos-labels-page)
|
||||||
|
- (Feature): [**Global and wiki configuration**](./usage-guide/configuration_options.md/#wiki-configuration-file)
|
||||||
|
- (Feature): [**Inline file summary**](https://pr-agent-docs.codium.ai/tools/describe/#inline-file-summary)
|
||||||
|
|
||||||
|
|
||||||
## Data privacy
|
## Data Privacy
|
||||||
|
|
||||||
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 PR-Agent with your OpenAI API key, it is between you and OpenAI. You can read their API data privacy policy here:
|
||||||
https://openai.com/enterprise-privacy
|
https://openai.com/enterprise-privacy
|
||||||
|
@ -7,9 +7,11 @@ You can use our pre-built Github Action Docker image to run PR-Agent as a Github
|
|||||||
```yaml
|
```yaml
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
types: [opened, reopened, ready_for_review]
|
||||||
issue_comment:
|
issue_comment:
|
||||||
jobs:
|
jobs:
|
||||||
pr_agent_job:
|
pr_agent_job:
|
||||||
|
if: ${{ github.event.sender.type != 'Bot' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
issues: write
|
issues: write
|
||||||
@ -24,27 +26,14 @@ jobs:
|
|||||||
OPENAI_KEY: ${{ secrets.OPENAI_KEY }}
|
OPENAI_KEY: ${{ secrets.OPENAI_KEY }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
```
|
```
|
||||||
** if you want to pin your action to a specific release (v0.7 for example) for stability reasons, use:
|
** if you want to pin your action to a specific release (v2.0 for example) for stability reasons, use:
|
||||||
```yaml
|
```yaml
|
||||||
on:
|
...
|
||||||
pull_request:
|
|
||||||
issue_comment:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
pr_agent_job:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
contents: write
|
|
||||||
name: Run pr agent on every pull request, respond to user comments
|
|
||||||
steps:
|
steps:
|
||||||
- name: PR Agent action step
|
- name: PR Agent action step
|
||||||
id: pragent
|
id: pragent
|
||||||
uses: Codium-ai/pr-agent@v0.7
|
uses: Codium-ai/pr-agent@v2.0
|
||||||
env:
|
...
|
||||||
OPENAI_KEY: ${{ secrets.OPENAI_KEY }}
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
```
|
```
|
||||||
2) Add the following secret to your repository under `Settings > Secrets and variables > Actions > New repository secret > Add secret`:
|
2) Add the following secret to your repository under `Settings > Secrets and variables > Actions > New repository secret > Add secret`:
|
||||||
|
|
||||||
@ -66,6 +55,7 @@ When you open your next PR, you should see a comment from `github-actions` bot w
|
|||||||
PR_REVIEWER.REQUIRE_TESTS_REVIEW: "false" # Disable tests review
|
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: 6 # Increase number of code suggestions
|
||||||
```
|
```
|
||||||
|
See detailed usage instructions in the [USAGE GUIDE](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/#github-action)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Installation
|
# Installation
|
||||||
|
|
||||||
## self-hosted PR-Agent
|
## Self-hosted PR-Agent
|
||||||
If you choose to host you own PR-Agent, you first need to acquire two tokens:
|
If you choose to host you own PR-Agent, you first need to acquire two tokens:
|
||||||
|
|
||||||
1. An OpenAI key from [here](https://platform.openai.com/api-keys), with access to GPT-4 (or a key for [other models](../usage-guide/additional_configurations.md/#changing-a-model), if you prefer).
|
1. An OpenAI key from [here](https://platform.openai.com/api-keys), with access to GPT-4 (or a key for [other models](../usage-guide/additional_configurations.md/#changing-a-model), if you prefer).
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
## Overview
|
## Overview
|
||||||
The `analyze` tool combines static code analysis with LLM capabilities to provide a comprehensive analysis of the PR code changes.
|
The `analyze` tool combines advanced static code analysis with LLM capabilities to provide a comprehensive analysis of the PR code changes.
|
||||||
|
|
||||||
The tool scans the PR code changes, find the code components (methods, functions, classes) that changed, and summarizes the changes in each component.
|
The tool scans the PR code changes, find the code components (methods, functions, classes) that changed, and enables to interactively generate tests, docs, code suggestions and similar code search for each component.
|
||||||
|
|
||||||
It can be invoked manually by commenting on any PR:
|
It can be invoked manually by commenting on any PR:
|
||||||
```
|
```
|
||||||
@ -9,14 +9,10 @@ It can be invoked manually by commenting on any PR:
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Example usage
|
## Example usage
|
||||||
An example [result](https://github.com/Codium-ai/pr-agent/pull/546#issuecomment-1868524805):
|
An example result:
|
||||||
|
|
||||||
{width=750}
|
{width=750}
|
||||||
→
|
|
||||||
{width=750}
|
|
||||||
→
|
|
||||||
{width=750}
|
|
||||||
|
|
||||||
**Notes**
|
**Notes**
|
||||||
|
|
||||||
- Language that are currently supported: Python, Java, C++, JavaScript, TypeScript.
|
- Language that are currently supported: Python, Java, C++, JavaScript, TypeScript, C#.
|
@ -7,9 +7,9 @@ It can be invoked manually by commenting on any PR:
|
|||||||
```
|
```
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
{width=768}
|
{width=512}
|
||||||
|
|
||||||
{width=768}
|
{width=512}
|
||||||
|
|
||||||
## Ask lines
|
## Ask lines
|
||||||
|
|
||||||
@ -18,6 +18,41 @@ You can run `/ask` on specific lines of code in the PR from the PR's diff view.
|
|||||||
- To select multiple lines, click on the '+' sign of the first line and then hold and drag to select the rest of the lines.
|
- To select multiple lines, click on the '+' sign of the first line and then hold and drag to select the rest of the lines.
|
||||||
- write `/ask "..."` in the comment box and press `Add single comment` button.
|
- write `/ask "..."` in the comment box and press `Add single comment` button.
|
||||||
|
|
||||||
{width=768}
|
{width=512}
|
||||||
|
|
||||||
Note that the tool does not have "memory" of previous questions, and answers each question independently.
|
Note that the tool does not have "memory" of previous questions, and answers each question independently.
|
||||||
|
|
||||||
|
## Ask on images
|
||||||
|
|
||||||
|
You can also ask questions about images that appear in the comment, where the entire PR code will be used as context.
|
||||||
|
<br>
|
||||||
|
The basic syntax is:
|
||||||
|
```
|
||||||
|
/ask "..."
|
||||||
|
|
||||||
|
[Image](https://real_link_to_image)
|
||||||
|
```
|
||||||
|
where `https://real_link_to_image` is the direct link to the image.
|
||||||
|
|
||||||
|
Note that GitHub has a built-in mechanism of pasting images in comments. However, pasted image does not provide a direct link.
|
||||||
|
To get a direct link to an image, we recommend using the following scheme:
|
||||||
|
|
||||||
|
1) First, post a comment that contains **only** the image:
|
||||||
|
|
||||||
|
{width=512}
|
||||||
|
|
||||||
|
2) Quote reply to that comment:
|
||||||
|
|
||||||
|
{width=512}
|
||||||
|
|
||||||
|
3) In the screen opened, type the question below the image:
|
||||||
|
|
||||||
|
{width=512}
|
||||||
|
{width=512}
|
||||||
|
|
||||||
|
4) Post the comment, and receive the answer:
|
||||||
|
|
||||||
|
{width=512}
|
||||||
|
|
||||||
|
|
||||||
|
See a full video tutorial [here](https://codium.ai/images/pr_agent/ask_image_video.mov)
|
@ -5,6 +5,7 @@ The tool can be triggered automatically every time a new PR is [opened](../usage
|
|||||||
```
|
```
|
||||||
/describe
|
/describe
|
||||||
```
|
```
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
{width=512}
|
{width=512}
|
||||||
@ -27,6 +28,8 @@ To edit [configurations](https://github.com/Codium-ai/pr-agent/blob/main/pr_agen
|
|||||||
|
|
||||||
- `publish_description_as_comment`: if set to true, the tool will publish the description as a comment to the PR. If false, it will overwrite the original description. Default is false.
|
- `publish_description_as_comment`: if set to true, the tool will publish the description as a comment to the PR. If false, it will overwrite the original description. Default is false.
|
||||||
|
|
||||||
|
- `publish_description_as_comment_persistent`: if set to true and `publish_description_as_comment` is true, the tool will publish the description as a persistent comment to the PR. Default is true.
|
||||||
|
|
||||||
- `add_original_user_description`: if set to true, the tool will add the original user description to the generated description. Default is true.
|
- `add_original_user_description`: if set to true, the tool will add the original user description to the generated description. Default is true.
|
||||||
|
|
||||||
- `generate_ai_title`: if set to true, the tool will automatically generate a title for the PR. If false, it will keep the original title. Default is false.
|
- `generate_ai_title`: if set to true, the tool will automatically generate a title for the PR. If false, it will keep the original title. Default is false.
|
||||||
@ -66,22 +69,6 @@ If you prefer to have the file summaries appear in the "Files changed" tab on ev
|
|||||||
**Note**: that this feature is currently available only for GitHub.
|
**Note**: that this feature is currently available only for GitHub.
|
||||||
|
|
||||||
|
|
||||||
### Handle custom labels from the Repo's labels page 💎
|
|
||||||
|
|
||||||
You can control the custom labels that will be suggested by the `describe` tool, from the repo's labels page:
|
|
||||||
|
|
||||||
* GitHub : go to `https://github.com/{owner}/{repo}/labels` (or click on the "Labels" tab in the issues or PRs page)
|
|
||||||
* GitLab : go to `https://gitlab.com/{owner}/{repo}/-/labels` (or click on "Manage" -> "Labels" on the left menu)
|
|
||||||
|
|
||||||
Now add/edit the custom labels. they should be formatted as follows:
|
|
||||||
|
|
||||||
* Label name: The name of the custom label.
|
|
||||||
* Description: Start the description of with prefix `pr_agent:`, for example: `pr_agent: Description of when AI should suggest this label`.<br>
|
|
||||||
|
|
||||||
The description should be comprehensive and detailed, indicating when to add the desired label. For example:
|
|
||||||
{width=768}
|
|
||||||
|
|
||||||
|
|
||||||
### Markers template
|
### Markers template
|
||||||
|
|
||||||
To enable markers, set `pr_description.use_description_markers=true`.
|
To enable markers, set `pr_description.use_description_markers=true`.
|
||||||
@ -114,6 +101,43 @@ The marker `pr_agent:type` will be replaced with the PR type, `pr_agent:summary`
|
|||||||
- `use_description_markers`: if set to true, the tool will use markers template. It replaces every marker of the form `pr_agent:marker_name` with the relevant content. Default is false.
|
- `use_description_markers`: if set to true, the tool will use markers template. It replaces every marker of the form `pr_agent:marker_name` with the relevant content. Default is false.
|
||||||
- `include_generated_by_header`: if set to true, the tool will add a dedicated header: 'Generated by PR Agent at ...' to any automatic content. Default is true.
|
- `include_generated_by_header`: if set to true, the tool will add a dedicated header: 'Generated by PR Agent at ...' to any automatic content. Default is true.
|
||||||
|
|
||||||
|
## Custom labels
|
||||||
|
|
||||||
|
The default labels of the describe tool are quite generic, since they are meant to be used in any repo: [`Bug fix`, `Tests`, `Enhancement`, `Documentation`, `Other`].
|
||||||
|
|
||||||
|
You can define custom labels that are relevant for your repo and use cases.
|
||||||
|
Custom labels can be defined in a [configuration file](https://pr-agent-docs.codium.ai/tools/custom_labels/#configuration-options), or directly in the repo's [labels page](#handle-custom-labels-from-the-repos-labels-page).
|
||||||
|
|
||||||
|
Examples for custom labels:
|
||||||
|
|
||||||
|
- `Main topic:performance` - pr_agent:The main topic of this PR is performance
|
||||||
|
- `New endpoint` - pr_agent:A new endpoint was added in this PR
|
||||||
|
- `SQL query` - pr_agent:A new SQL query was added in this PR
|
||||||
|
- `Dockerfile changes` - pr_agent:The PR contains changes in the Dockerfile
|
||||||
|
- ...
|
||||||
|
|
||||||
|
The list above is eclectic, and aims to give an idea of different possibilities. Define custom labels that are relevant for your repo and use cases.
|
||||||
|
Note that Labels are not mutually exclusive, so you can add multiple label categories.
|
||||||
|
<br>
|
||||||
|
Make sure to provide proper title, and a detailed and well-phrased description for each label, so the tool will know when to suggest it.
|
||||||
|
Each label description should be a **conditional statement**, that indicates if to add the label to the PR or not, according to the PR content.
|
||||||
|
|
||||||
|
|
||||||
|
### Handle custom labels from the Repo's labels page 💎
|
||||||
|
|
||||||
|
You can control the custom labels that will be suggested by the `describe` tool, from the repo's labels page:
|
||||||
|
|
||||||
|
* GitHub : go to `https://github.com/{owner}/{repo}/labels` (or click on the "Labels" tab in the issues or PRs page)
|
||||||
|
* GitLab : go to `https://gitlab.com/{owner}/{repo}/-/labels` (or click on "Manage" -> "Labels" on the left menu)
|
||||||
|
|
||||||
|
Now add/edit the custom labels. they should be formatted as follows:
|
||||||
|
|
||||||
|
* Label name: The name of the custom label.
|
||||||
|
* Description: Start the description of with prefix `pr_agent:`, for example: `pr_agent: Description of when AI should suggest this label`.<br>
|
||||||
|
|
||||||
|
The description should be comprehensive and detailed, indicating when to add the desired label. For example:
|
||||||
|
{width=768}
|
||||||
|
|
||||||
|
|
||||||
## Usage Tips
|
## Usage Tips
|
||||||
|
|
||||||
@ -142,20 +166,3 @@ The marker `pr_agent:type` will be replaced with the PR type, `pr_agent:summary`
|
|||||||
* `walkthrough`: the PR walkthrough.
|
* `walkthrough`: the PR walkthrough.
|
||||||
|
|
||||||
- Note that when markers are enabled, if the original PR description does not contain any markers, the tool will not alter the description at all.
|
- Note that when markers are enabled, if the original PR description does not contain any markers, the tool will not alter the description at all.
|
||||||
|
|
||||||
!!! tip "Custom labels"
|
|
||||||
|
|
||||||
The default labels of the describe tool are quite generic, since they are meant to be used in any repo: [`Bug fix`, `Tests`, `Enhancement`, `Documentation`, `Other`].
|
|
||||||
|
|
||||||
If you specify [custom labels](#handle-custom-labels-from-the-repos-labels-page) in the repo's labels page, you can get tailored labels for your use cases.
|
|
||||||
Examples for custom labels:
|
|
||||||
|
|
||||||
- `Main topic:performance` - pr_agent:The main topic of this PR is performance
|
|
||||||
- `New endpoint` - pr_agent:A new endpoint was added in this PR
|
|
||||||
- `SQL query` - pr_agent:A new SQL query was added in this PR
|
|
||||||
- `Dockerfile changes` - pr_agent:The PR contains changes in the Dockerfile
|
|
||||||
- ...
|
|
||||||
|
|
||||||
The list above is eclectic, and aims to give an idea of different possibilities. Define custom labels that are relevant for your repo and use cases.
|
|
||||||
Note that Labels are not mutually exclusive, so you can add multiple label categories.
|
|
||||||
<br>Make sure to provide proper title, and a detailed and well-phrased description for each label, so the tool will know when to suggest it.
|
|
@ -19,6 +19,6 @@ For example:
|
|||||||
|
|
||||||
**Notes**
|
**Notes**
|
||||||
|
|
||||||
- Language that are currently fully supported: Python, Java, C++, JavaScript, TypeScript.
|
- Language that are currently fully supported: Python, Java, C++, JavaScript, TypeScript, C#.
|
||||||
- For languages that are not fully supported, the tool will suggest documentation only for new components in the PR.
|
- For languages that are not fully supported, the tool will suggest documentation only for new components in the PR.
|
||||||
- A previous version of the tool, that offered support only for new components, was deprecated.
|
- A previous version of the tool, that offered support only for new components, was deprecated.
|
17
docs/docs/tools/help.md
Normal file
17
docs/docs/tools/help.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
## Overview
|
||||||
|
The `help` tool provides a list of all the available tools and their descriptions.
|
||||||
|
For PR-Agent Pro users, it also enables to trigger each tool by checking the relevant box.
|
||||||
|
|
||||||
|
It can be invoked manually by commenting on any PR:
|
||||||
|
```
|
||||||
|
/help
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example usage
|
||||||
|
An example [result](https://github.com/Codium-ai/pr-agent/pull/546#issuecomment-1868524805):
|
||||||
|
|
||||||
|
{width=750}
|
||||||
|
|
||||||
|
→
|
||||||
|
|
||||||
|
{width=750}
|
@ -72,7 +72,7 @@ To edit [configurations](https://github.com/Codium-ai/pr-agent/blob/main/pr_agen
|
|||||||
Examples for extra instructions:
|
Examples for extra instructions:
|
||||||
```
|
```
|
||||||
[pr_code_suggestions] # /improve #
|
[pr_code_suggestions] # /improve #
|
||||||
extra_instructions="""
|
extra_instructions="""\
|
||||||
Emphasize the following aspects:
|
Emphasize the following aspects:
|
||||||
- Does the code logic cover relevant edge cases?
|
- Does the code logic cover relevant edge cases?
|
||||||
- Is the code logic clear and easy to understand?
|
- Is the code logic clear and easy to understand?
|
||||||
|
24
docs/docs/tools/improve_component.md
Normal file
24
docs/docs/tools/improve_component.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
## Overview
|
||||||
|
The `improve_component` tool generates code suggestions for a specific code component that changed in the PR.
|
||||||
|
it can be invoked manually by commenting on any PR:
|
||||||
|
```
|
||||||
|
/improve_component component_name
|
||||||
|
```
|
||||||
|
|
||||||
|
To get a list of the components that changed in the PR and choose the relevant component interactively, use the [`analyze`](./analyze.md) tool.
|
||||||
|
|
||||||
|
|
||||||
|
Example result:
|
||||||
|
|
||||||
|
{width=768}
|
||||||
|
|
||||||
|
{width=768}
|
||||||
|
|
||||||
|
**Notes**
|
||||||
|
- Language that are currently supported by the tool: Python, Java, C++, JavaScript, TypeScript, C#.
|
||||||
|
|
||||||
|
## Configuration options
|
||||||
|
- `num_code_suggestions`: number of code suggestions to provide. Default is 4
|
||||||
|
- `extra_instructions`: Optional extra instructions to the tool. For example: "focus on ...".
|
||||||
|
- `file`: in case there are several components with the same name, you can specify the relevant file.
|
||||||
|
- `class_name`: in case there are several methods with the same name in the same file, you can specify the relevant class name.
|
@ -2,19 +2,21 @@
|
|||||||
|
|
||||||
Here is a list of PR-Agent tools, each with a dedicated page that explains how to use it:
|
Here is a list of PR-Agent tools, each with a dedicated page that explains how to use it:
|
||||||
|
|
||||||
| Tool | Description |
|
| Tool | Description |
|
||||||
|-------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
|
|------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| **[PR Description (`/describe`](./describe.md))** | Automatically generating PR description - title, type, summary, code walkthrough and labels |
|
| **[PR Description (`/describe`](./describe.md))** | Automatically generating PR description - title, type, summary, code walkthrough and labels |
|
||||||
| **[PR Review (`/review`](./review.md))** | Adjustable feedback about the PR, possible issues, security concerns, review effort and more |
|
| **[PR Review (`/review`](./review.md))** | Adjustable feedback about the PR, possible issues, security concerns, review effort and more |
|
||||||
| **[Code Suggestions (`/improve`](./improve.md))** | Code suggestions for improving the PR |
|
| **[Code Suggestions (`/improve`](./improve.md))** | Code suggestions for improving the PR |
|
||||||
| **[Question Answering (`/ask ...`](./ask.md))** | Answering free-text questions about the PR, or on specific code lines |
|
| **[Question Answering (`/ask ...`](./ask.md))** | Answering free-text questions about the PR, or on specific code lines |
|
||||||
| **[Update Changelog (`/update_changelog`](./update_changelog.md))** | Automatically updating the CHANGELOG.md file with the PR changes |
|
| **[Update Changelog (`/update_changelog`](./update_changelog.md))** | Automatically updating the CHANGELOG.md file with the PR changes |
|
||||||
| **[Find Similar Issue (`/similar_issue`](./similar_issues.md))** | Automatically retrieves and presents similar issues |
|
| **[Find Similar Issue (`/similar_issue`](./similar_issues.md))** | Automatically retrieves and presents similar issues |
|
||||||
| **💎 [Add Documentation (`/add_docs`](./documentation.md))** | Generates documentation to methods/functions/classes that changed in the PR |
|
| **[Help (`/help`](./help.md))** | Provides a list of all the available tools. Also enables to trigger them interactively (💎) |
|
||||||
| **💎 [Generate Custom Labels (`/generate_labels`](./custom_labels.md))** | Generates custom labels for the PR, based on specific guidelines defined by the user |
|
| **💎 [Add Documentation (`/add_docs`](./documentation.md))** | Generates documentation to methods/functions/classes that changed in the PR |
|
||||||
| **💎 [Analyze (`/analyze`](./analyze.md))** | Identify code components that changed in the PR, and enables to interactively generate tests, docs, and code suggestions for each component |
|
| **💎 [Generate Custom Labels (`/generate_labels`](./custom_labels.md))** | Generates custom labels for the PR, based on specific guidelines defined by the user |
|
||||||
| **💎 [Custom Suggestions (`/custom_suggestions`](./custom_suggestions.md))** | Automatically generates custom suggestions for improving the PR code, based on specific guidelines defined by the user |
|
| **💎 [Analyze (`/analyze`](./analyze.md))** | Identify code components that changed in the PR, and enables to interactively generate tests, docs, and code suggestions for each component |
|
||||||
| **💎 [Generate Tests (`/test component_name`](./test.md))** | Automatically generates unit tests for a selected component, based on the PR code changes |
|
| **💎 [Custom Suggestions (`/custom_suggestions`](./custom_suggestions.md))** | Automatically generates custom suggestions for improving the PR code, based on specific guidelines defined by the user |
|
||||||
| **💎 [CI Feedback (`/checks ci_job`](./ci_feedback.md))** | Automatically generates feedback and analysis for a failed CI job |
|
| **💎 [Generate Tests (`/test component_name`](./test.md))** | Automatically generates unit tests for a selected component, based on the PR code changes |
|
||||||
|
| **💎 [Improve Component (`/improve_component component_name`](./improve_component.md))** | Generates code suggestions for a specific code component that changed in the PR |
|
||||||
|
| **💎 [CI Feedback (`/checks ci_job`](./ci_feedback.md))** | Automatically generates feedback and analysis for a failed CI job |
|
||||||
|
|
||||||
Note that the tools marked with 💎 are available only for PR-Agent Pro users.
|
Note that the tools marked with 💎 are available only for PR-Agent Pro users.
|
@ -124,8 +124,8 @@ The tool will first ask the author questions about the PR, and will guide the re
|
|||||||
|
|
||||||
Examples for extra instructions:
|
Examples for extra instructions:
|
||||||
```
|
```
|
||||||
[pr_reviewer] # /review #
|
[pr_reviewer]
|
||||||
extra_instructions="""
|
extra_instructions="""\
|
||||||
In the code feedback section, emphasize the following:
|
In the code feedback section, emphasize the following:
|
||||||
- Does the code logic cover relevant edge cases?
|
- Does the code logic cover relevant edge cases?
|
||||||
- Is the code logic clear and easy to understand?
|
- Is the code logic clear and easy to understand?
|
||||||
|
@ -5,7 +5,7 @@ It can be invoked manually by commenting on any PR:
|
|||||||
/test component_name
|
/test component_name
|
||||||
```
|
```
|
||||||
where 'component_name' is the name of a specific component in the PR.
|
where 'component_name' is the name of a specific component in the PR.
|
||||||
To get a list of the components that changed in the PR, use the [`analyze`](./analyze.md) tool.
|
To get a list of the components that changed in the PR and choose the relevant component interactively, use the [`analyze`](./analyze.md) tool.
|
||||||
|
|
||||||
|
|
||||||
An example [result](https://github.com/Codium-ai/pr-agent/pull/598#issuecomment-1913679429):
|
An example [result](https://github.com/Codium-ai/pr-agent/pull/598#issuecomment-1913679429):
|
||||||
@ -17,7 +17,7 @@ An example [result](https://github.com/Codium-ai/pr-agent/pull/598#issuecomment-
|
|||||||
{width=768}
|
{width=768}
|
||||||
|
|
||||||
**Notes**
|
**Notes**
|
||||||
- Language that are currently supported by the tool: Python, Java, C++, JavaScript, TypeScript.
|
- Language that are currently supported by the tool: Python, Java, C++, JavaScript, TypeScript, C#.
|
||||||
|
|
||||||
|
|
||||||
## Configuration options
|
## Configuration options
|
||||||
|
@ -7,10 +7,10 @@ To ignore files or directories, edit the **[ignore.toml](https://github.com/Codi
|
|||||||
- `IGNORE.GLOB`
|
- `IGNORE.GLOB`
|
||||||
- `IGNORE.REGEX`
|
- `IGNORE.REGEX`
|
||||||
|
|
||||||
For example, to ignore python files in a PR with online usage, comment on a PR:
|
For example, to ignore Python files in a PR with online usage, comment on a PR:
|
||||||
`/review --ignore.glob=['*.py']`
|
`/review --ignore.glob=['*.py']`
|
||||||
|
|
||||||
To ignore python files in all PRs, set in a configuration file:
|
To ignore Python files in all PRs, set in a configuration file:
|
||||||
```
|
```
|
||||||
[ignore]
|
[ignore]
|
||||||
glob = ['*.py']
|
glob = ['*.py']
|
||||||
@ -26,13 +26,13 @@ All PR-Agent tools have a parameter called `extra_instructions`, that enables to
|
|||||||
## Working with large PRs
|
## Working with large PRs
|
||||||
|
|
||||||
The default mode of CodiumAI is to have a single call per tool, using GPT-4, which has a token limit of 8000 tokens.
|
The default mode of CodiumAI is to have a single call per tool, using GPT-4, which has a token limit of 8000 tokens.
|
||||||
This mode provide a very good speed-quality-cost tradeoff, and can handle most PRs successfully.
|
This mode provides a very good speed-quality-cost tradeoff, and can handle most PRs successfully.
|
||||||
When the PR is above the token limit, it employs a [PR Compression strategy](../core-abilities/index.md).
|
When the PR is above the token limit, it employs a [PR Compression strategy](../core-abilities/index.md).
|
||||||
|
|
||||||
However, for very large PRs, or in case you want to emphasize quality over speed and cost, there are 2 possible solutions:
|
However, for very large PRs, or in case you want to emphasize quality over speed and cost, there are two possible solutions:
|
||||||
1) [Use a model](https://codium-ai.github.io/Docs-PR-Agent/usage-guide/#changing-a-model) with larger context, like GPT-32K, or claude-100K. This solution will be applicable for all the tools.
|
1) [Use a model](https://codium-ai.github.io/Docs-PR-Agent/usage-guide/#changing-a-model) with larger context, like GPT-32K, or claude-100K. This solution will be applicable for all the tools.
|
||||||
2) For the `/improve` tool, there is an ['extended' mode](https://codium-ai.github.io/Docs-PR-Agent/tools/#improve) (`/improve --extended`),
|
2) For the `/improve` tool, there is an ['extended' mode](https://codium-ai.github.io/Docs-PR-Agent/tools/#improve) (`/improve --extended`),
|
||||||
which divides the PR to chunks, and process each chunk separately. With this mode, regardless of the model, no compression will be done (but for large PRs, multiple model calls may occur)
|
which divides the PR to chunks, and processes each chunk separately. With this mode, regardless of the model, no compression will be done (but for large PRs, multiple model calls may occur)
|
||||||
|
|
||||||
|
|
||||||
## Changing a model
|
## Changing a model
|
||||||
@ -79,6 +79,7 @@ MAX_TOKENS={
|
|||||||
|
|
||||||
[config] # in configuration.toml
|
[config] # in configuration.toml
|
||||||
model = "ollama/llama2"
|
model = "ollama/llama2"
|
||||||
|
model_turbo = "ollama/llama2"
|
||||||
|
|
||||||
[ollama] # in .secrets.toml
|
[ollama] # in .secrets.toml
|
||||||
api_base = ... # the base url for your huggingface inference endpoint
|
api_base = ... # the base url for your huggingface inference endpoint
|
||||||
@ -101,6 +102,7 @@ MAX_TOKENS={
|
|||||||
}
|
}
|
||||||
[config] # in configuration.toml
|
[config] # in configuration.toml
|
||||||
model = "huggingface/meta-llama/Llama-2-7b-chat-hf"
|
model = "huggingface/meta-llama/Llama-2-7b-chat-hf"
|
||||||
|
model_turbo = "huggingface/meta-llama/Llama-2-7b-chat-hf"
|
||||||
|
|
||||||
[huggingface] # in .secrets.toml
|
[huggingface] # in .secrets.toml
|
||||||
key = ... # your huggingface api key
|
key = ... # your huggingface api key
|
||||||
@ -114,13 +116,14 @@ To use Llama2 model with Replicate, for example, set:
|
|||||||
```
|
```
|
||||||
[config] # in configuration.toml
|
[config] # in configuration.toml
|
||||||
model = "replicate/llama-2-70b-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1"
|
model = "replicate/llama-2-70b-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1"
|
||||||
|
model_turbo = "replicate/llama-2-70b-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1"
|
||||||
[replicate] # in .secrets.toml
|
[replicate] # in .secrets.toml
|
||||||
key = ...
|
key = ...
|
||||||
```
|
```
|
||||||
(you can obtain a Llama2 key from [here](https://replicate.com/replicate/llama-2-70b-chat/api))
|
(you can obtain a Llama2 key from [here](https://replicate.com/replicate/llama-2-70b-chat/api))
|
||||||
|
|
||||||
|
|
||||||
Also review the [AiHandler](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/algo/ai_handler.py) file for instruction how to set keys for other models.
|
Also, review the [AiHandler](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/algo/ai_handler.py) file for instructions on how to set keys for other models.
|
||||||
|
|
||||||
### Vertex AI
|
### Vertex AI
|
||||||
|
|
||||||
@ -129,6 +132,7 @@ To use Google's Vertex AI platform and its associated models (chat-bison/codecha
|
|||||||
```
|
```
|
||||||
[config] # in configuration.toml
|
[config] # in configuration.toml
|
||||||
model = "vertex_ai/codechat-bison"
|
model = "vertex_ai/codechat-bison"
|
||||||
|
model_turbo = "vertex_ai/codechat-bison"
|
||||||
fallback_models="vertex_ai/codechat-bison"
|
fallback_models="vertex_ai/codechat-bison"
|
||||||
|
|
||||||
[vertexai] # in .secrets.toml
|
[vertexai] # in .secrets.toml
|
||||||
@ -183,7 +187,7 @@ AWS session is automatically authenticated from your environment, but you can al
|
|||||||
|
|
||||||
## Patch Extra Lines
|
## Patch Extra Lines
|
||||||
|
|
||||||
By default, around any change in your PR, git patch provides 3 lines of context above and below the change.
|
By default, around any change in your PR, git patch provides three lines of context above and below the change.
|
||||||
```
|
```
|
||||||
@@ -12,5 +12,5 @@ def func1():
|
@@ -12,5 +12,5 @@ def func1():
|
||||||
code line that already existed in the file...
|
code line that already existed in the file...
|
||||||
|
@ -50,6 +50,10 @@ Any configuration value in [configuration file](https://github.com/Codium-ai/pr-
|
|||||||
|
|
||||||
## GitHub App
|
## GitHub App
|
||||||
|
|
||||||
|
!!! note "Configurations for PR-Agent Pro"
|
||||||
|
PR-Agent Pro for GitHub is an App, hosted by CodiumAI. So all the instructions below are relevant also for PR-Agent Pro users.
|
||||||
|
Same goes for [GitLab webhook](#gitlab-webhook) and [BitBucket App](#bitbucket-app) sections.
|
||||||
|
|
||||||
### GitHub app automatic tools when a new PR is opened
|
### GitHub app automatic tools when a new PR is opened
|
||||||
|
|
||||||
The [github_app](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L108) section defines GitHub app specific configurations.
|
The [github_app](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L108) section defines GitHub app specific configurations.
|
||||||
@ -59,7 +63,7 @@ The configuration parameter `pr_commands` defines the list of tools that will be
|
|||||||
[github_app]
|
[github_app]
|
||||||
pr_commands = [
|
pr_commands = [
|
||||||
"/describe --pr_description.add_original_user_description=true --pr_description.keep_original_user_title=true --pr_description.final_update_message=false",
|
"/describe --pr_description.add_original_user_description=true --pr_description.keep_original_user_title=true --pr_description.final_update_message=false",
|
||||||
"/review --pr_reviewer.num_code_suggestions=0 --pr_reviewer.final_update_message=false",
|
"/review --pr_reviewer.num_code_suggestions=0",
|
||||||
"/improve",
|
"/improve",
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
@ -99,13 +103,13 @@ The configuration parameter `push_commands` defines the list of tools that will
|
|||||||
handle_push_trigger = true
|
handle_push_trigger = true
|
||||||
push_commands = [
|
push_commands = [
|
||||||
"/describe --pr_description.add_original_user_description=true --pr_description.keep_original_user_title=true",
|
"/describe --pr_description.add_original_user_description=true --pr_description.keep_original_user_title=true",
|
||||||
"/review --pr_reviewer.num_code_suggestions=0",
|
"/review --pr_reviewer.num_code_suggestions=0 --pr_reviewer.final_update_message=false",
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
This means that when new code is pushed to the PR, the PR-Agent will run the `describe` and `review` tools, with the specified parameters.
|
This means that when new code is pushed to the PR, the PR-Agent will run the `describe` and `review` tools, with the specified parameters.
|
||||||
|
|
||||||
## GitHub Action
|
## GitHub Action
|
||||||
`GitHub Action` is a different way to trigger PR-Agent tools, and uses a different configuration mechanism than `GitHub App`.
|
`GitHub Action` is a different way to trigger PR-Agent tools, and uses a different configuration mechanism than `GitHub App`.<br>
|
||||||
You can configure settings for `GitHub Action` by adding environment variables under the env section in `.github/workflows/pr_agent.yml` file.
|
You can configure settings for `GitHub Action` by adding environment variables under the env section in `.github/workflows/pr_agent.yml` file.
|
||||||
Specifically, start by setting the following environment variables:
|
Specifically, start by setting the following environment variables:
|
||||||
```yaml
|
```yaml
|
||||||
@ -115,17 +119,23 @@ Specifically, start by setting the following environment variables:
|
|||||||
github_action_config.auto_review: "true" # enable\disable auto review
|
github_action_config.auto_review: "true" # enable\disable auto review
|
||||||
github_action_config.auto_describe: "true" # enable\disable auto describe
|
github_action_config.auto_describe: "true" # enable\disable auto describe
|
||||||
github_action_config.auto_improve: "true" # enable\disable auto improve
|
github_action_config.auto_improve: "true" # enable\disable auto improve
|
||||||
|
github_action_config.enable_output: "true" # enable\disable github actions output parameter
|
||||||
```
|
```
|
||||||
`github_action_config.auto_review`, `github_action_config.auto_describe` and `github_action_config.auto_improve` are used to enable/disable automatic tools that run when a new PR is opened.
|
`github_action_config.auto_review`, `github_action_config.auto_describe` and `github_action_config.auto_improve` are used to enable/disable automatic tools that run when a new PR is opened.
|
||||||
If not set, the default configuration is for all three tools to run automatically when a new PR is opened.
|
If not set, the default configuration is for all three tools to run automatically when a new PR is opened.
|
||||||
|
|
||||||
Note that you can give additional config parameters by adding environment variables to `.github/workflows/pr_agent.yml`, or by using a `.pr_agent.toml` file in the root of your repo, similar to the GitHub App usage.
|
`github_action_config.enable_output` are used to enable/disable github actions [output parameter](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#outputs-for-docker-container-and-javascript-actions) (default is `true`).
|
||||||
|
Review result is output as JSON to `steps.{step-id}.outputs.review` property.
|
||||||
|
The JSON structure is equivalent to the yaml data structure defined in [pr_reviewer_prompts.toml](https://github.com/idubnori/pr-agent/blob/main/pr_agent/settings/pr_reviewer_prompts.toml).
|
||||||
|
|
||||||
For example, you can set an environment variable: `pr_description.add_original_user_description=false`, or add a `.pr_agent.toml` file with the following content:
|
Note that you can give additional config parameters by adding environment variables to `.github/workflows/pr_agent.yml`, or by using a `.pr_agent.toml` [configuration file](https://pr-agent-docs.codium.ai/usage-guide/configuration_options/#global-configuration-file) in the root of your repo
|
||||||
|
|
||||||
|
For example, you can set an environment variable: `pr_description.publish_labels=false`, or add a `.pr_agent.toml` file with the following content:
|
||||||
```
|
```
|
||||||
[pr_description]
|
[pr_description]
|
||||||
add_original_user_description = false
|
publish_labels = false
|
||||||
```
|
```
|
||||||
|
to prevent PR-Agent from publishing labels when running the `describe` tool.
|
||||||
|
|
||||||
## GitLab Webhook
|
## GitLab Webhook
|
||||||
After setting up a GitLab webhook, to control which commands will run automatically when a new PR is opened, you can set the `pr_commands` parameter in the configuration file, similar to the GitHub App:
|
After setting up a GitLab webhook, to control which commands will run automatically when a new PR is opened, you can set the `pr_commands` parameter in the configuration file, similar to the GitHub App:
|
||||||
@ -153,11 +163,11 @@ Each time you invoke a `/review` tool, it will use inline code comments.
|
|||||||
|
|
||||||
### BitBucket Self-Hosted App automatic tools
|
### BitBucket Self-Hosted App automatic tools
|
||||||
|
|
||||||
to control which commands will run automatically when a new PR is opened, you can set the `pr_commands` parameter in the configuration file:
|
To control which commands will run automatically when a new PR is opened, you can set the `pr_commands` parameter in the configuration file:
|
||||||
Specifically, set the following values:
|
Specifically, set the following values:
|
||||||
|
|
||||||
[bitbucket_app]
|
|
||||||
```
|
```
|
||||||
|
[bitbucket_app]
|
||||||
pr_commands = [
|
pr_commands = [
|
||||||
"/review --pr_reviewer.num_code_suggestions=0",
|
"/review --pr_reviewer.num_code_suggestions=0",
|
||||||
"/improve --pr_code_suggestions.summarize=false",
|
"/improve --pr_code_suggestions.summarize=false",
|
||||||
@ -196,4 +206,4 @@ pr_commands = [
|
|||||||
"/review --pr_reviewer.num_code_suggestions=0",
|
"/review --pr_reviewer.num_code_suggestions=0",
|
||||||
"/improve",
|
"/improve",
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
@ -22,7 +22,7 @@ Click [here](https://codium.ai/images/pr_agent/wiki_configuration_pr_agent.mp4)
|
|||||||
An example content:
|
An example content:
|
||||||
|
|
||||||
```
|
```
|
||||||
[pr_description] # /describe #
|
[pr_description]
|
||||||
keep_original_user_title=false
|
keep_original_user_title=false
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
# Usage guide
|
# Usage guide
|
||||||
|
|
||||||
|
This page provides a detailed guide on how to use PR-Agent. It includes information on how to adjust PR-Agent configurations, define which tools will run automatically, manage mail notifications, and other advanced configurations.
|
||||||
|
|
||||||
|
|
||||||
- [Introduction](./introduction.md)
|
- [Introduction](./introduction.md)
|
||||||
- [Configuration Options](./configuration_options.md)
|
- [Configuration Options](./configuration_options.md)
|
||||||
- [Managing Mail Notifications](./mail_notifications.md)
|
|
||||||
- [Usage and Automation](./automations_and_usage.md)
|
- [Usage and Automation](./automations_and_usage.md)
|
||||||
- [Local Repo (CLI)](./automations_and_usage.md#local-repo-cli)
|
- [Local Repo (CLI)](./automations_and_usage.md#local-repo-cli)
|
||||||
- [Online Usage](./automations_and_usage.md#online-usage)
|
- [Online Usage](./automations_and_usage.md#online-usage)
|
||||||
@ -11,6 +13,7 @@
|
|||||||
- [GitLab Webhook](./automations_and_usage.md#gitlab-webhook)
|
- [GitLab Webhook](./automations_and_usage.md#gitlab-webhook)
|
||||||
- [BitBucket App](./automations_and_usage.md#bitbucket-app)
|
- [BitBucket App](./automations_and_usage.md#bitbucket-app)
|
||||||
- [Azure DevOps Provider](./automations_and_usage.md#azure-devops-provider)
|
- [Azure DevOps Provider](./automations_and_usage.md#azure-devops-provider)
|
||||||
|
- [Managing Mail Notifications](./mail_notifications.md)
|
||||||
- [Additional Configurations Walkthrough](./additional_configurations.md)
|
- [Additional Configurations Walkthrough](./additional_configurations.md)
|
||||||
- [Ignoring files from analysis](./additional_configurations.md#ignoring-files-from-analysis)
|
- [Ignoring files from analysis](./additional_configurations.md#ignoring-files-from-analysis)
|
||||||
- [Extra instructions](./additional_configurations.md#extra-instructions)
|
- [Extra instructions](./additional_configurations.md#extra-instructions)
|
||||||
|
@ -7,3 +7,12 @@ If you are subscribed to notifications for a repo with PR-Agent, we recommend tu
|
|||||||
As an alternative, you can filter in your mail provider the notifications specifically from the PR-Agent bot, [see how](https://www.quora.com/How-can-you-filter-emails-for-specific-people-in-Gmail#:~:text=On%20the%20Filters%20and%20Blocked,the%20body%20of%20the%20email).
|
As an alternative, you can filter in your mail provider the notifications specifically from the PR-Agent bot, [see how](https://www.quora.com/How-can-you-filter-emails-for-specific-people-in-Gmail#:~:text=On%20the%20Filters%20and%20Blocked,the%20body%20of%20the%20email).
|
||||||
|
|
||||||
{width=512}
|
{width=512}
|
||||||
|
|
||||||
|
|
||||||
|
Another option to reduce the mail overload, yet still receive notifications on PR-Agent tools, is to disable the help collapsible section in PR-Agent bot comments.
|
||||||
|
This can done by setting `enable_help_text=false` for the relevant tool in the configuration file.
|
||||||
|
For example, to disable the help text for the `pr_reviewer` tool, set:
|
||||||
|
```
|
||||||
|
[pr_reviewer]
|
||||||
|
enable_help_text = false
|
||||||
|
```
|
@ -1,4 +1,6 @@
|
|||||||
site_name: PR-Agent
|
site_name: PR-Agent Documentation
|
||||||
|
repo_url: https://github.com/Codium-ai/pr-agent
|
||||||
|
repo_name: Codium-ai/pr-agent
|
||||||
|
|
||||||
nav:
|
nav:
|
||||||
- Overview: 'index.md'
|
- Overview: 'index.md'
|
||||||
@ -14,7 +16,7 @@ nav:
|
|||||||
- 'usage-guide/index.md'
|
- 'usage-guide/index.md'
|
||||||
- Introduction: 'usage-guide/introduction.md'
|
- Introduction: 'usage-guide/introduction.md'
|
||||||
- Configuration Options: 'usage-guide/configuration_options.md'
|
- Configuration Options: 'usage-guide/configuration_options.md'
|
||||||
- Managing email notifications: 'usage-guide/mail_notifications.md'
|
- Managing Mail Notifications: 'usage-guide/mail_notifications.md'
|
||||||
- Usage and Automation: 'usage-guide/automations_and_usage.md'
|
- Usage and Automation: 'usage-guide/automations_and_usage.md'
|
||||||
- Additional Configurations: 'usage-guide/additional_configurations.md'
|
- Additional Configurations: 'usage-guide/additional_configurations.md'
|
||||||
- Tools:
|
- Tools:
|
||||||
@ -25,8 +27,10 @@ nav:
|
|||||||
- Ask: 'tools/ask.md'
|
- Ask: 'tools/ask.md'
|
||||||
- Update Changelog: 'tools/update_changelog.md'
|
- Update Changelog: 'tools/update_changelog.md'
|
||||||
- Similar Issues: 'tools/similar_issues.md'
|
- Similar Issues: 'tools/similar_issues.md'
|
||||||
|
- Help: 'tools/help.md'
|
||||||
- 💎 Analyze: 'tools/analyze.md'
|
- 💎 Analyze: 'tools/analyze.md'
|
||||||
- 💎 Test: 'tools/test.md'
|
- 💎 Test: 'tools/test.md'
|
||||||
|
- 💎 Improve Component: 'tools/improve_component.md'
|
||||||
- 💎 Documentation: 'tools/documentation.md'
|
- 💎 Documentation: 'tools/documentation.md'
|
||||||
- 💎 Custom Labels: 'tools/custom_labels.md'
|
- 💎 Custom Labels: 'tools/custom_labels.md'
|
||||||
- 💎 Custom Suggestions: 'tools/custom_suggestions.md'
|
- 💎 Custom Suggestions: 'tools/custom_suggestions.md'
|
||||||
@ -38,6 +42,8 @@ theme:
|
|||||||
logo: assets/logo.svg
|
logo: assets/logo.svg
|
||||||
favicon: assets/favicon.ico
|
favicon: assets/favicon.ico
|
||||||
name: material
|
name: material
|
||||||
|
icon:
|
||||||
|
repo: fontawesome/brands/github
|
||||||
features:
|
features:
|
||||||
- navigation.tabs
|
- navigation.tabs
|
||||||
- navigation.expand
|
- navigation.expand
|
||||||
@ -95,7 +101,7 @@ extra:
|
|||||||
- icon: fontawesome/brands/instagram
|
- icon: fontawesome/brands/instagram
|
||||||
link: https://www.instagram.com/codiumai/
|
link: https://www.instagram.com/codiumai/
|
||||||
analytics:
|
analytics:
|
||||||
provider: google
|
provider: custom
|
||||||
property: ${{ secrets.GOOGLE_ANALYTICS_ID }}
|
property: ${{ secrets.GOOGLE_ANALYTICS_ID }}
|
||||||
|
|
||||||
extra_css:
|
extra_css:
|
||||||
|
10
docs/overrides/main.html
Normal file
10
docs/overrides/main.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
{{ super() }}
|
||||||
|
|
||||||
|
<!-- Google Tag Manager (noscript) -->
|
||||||
|
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5C9KZBM3"
|
||||||
|
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
|
||||||
|
<!-- End Google Tag Manager (noscript) -->
|
||||||
|
{% endblock %}
|
@ -0,0 +1,7 @@
|
|||||||
|
<!-- Google Tag Manager -->
|
||||||
|
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||||
|
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
||||||
|
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||||
|
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||||
|
})(window,document,'script','dataLayer','GTM-5C9KZBM3');</script>
|
||||||
|
<!-- End Google Tag Manager -->
|
@ -73,6 +73,9 @@ class PRAgent:
|
|||||||
args = update_settings_from_args(args)
|
args = update_settings_from_args(args)
|
||||||
|
|
||||||
action = action.lstrip("/").lower()
|
action = action.lstrip("/").lower()
|
||||||
|
if action not in command2class:
|
||||||
|
get_logger().debug(f"Unknown command: {action}")
|
||||||
|
return False
|
||||||
with get_logger().contextualize(command=action):
|
with get_logger().contextualize(command=action):
|
||||||
get_logger().info("PR-Agent request handler started", analytics=True)
|
get_logger().info("PR-Agent request handler started", analytics=True)
|
||||||
if action == "reflect_and_review":
|
if action == "reflect_and_review":
|
||||||
|
@ -11,6 +11,8 @@ MAX_TOKENS = {
|
|||||||
'gpt-4-1106-preview': 128000, # 128K, but may be limited by config.max_model_tokens
|
'gpt-4-1106-preview': 128000, # 128K, but may be limited by config.max_model_tokens
|
||||||
'gpt-4-0125-preview': 128000, # 128K, but may be limited by config.max_model_tokens
|
'gpt-4-0125-preview': 128000, # 128K, but may be limited by config.max_model_tokens
|
||||||
'gpt-4-turbo-preview': 128000, # 128K, but may be limited by config.max_model_tokens
|
'gpt-4-turbo-preview': 128000, # 128K, but may be limited by config.max_model_tokens
|
||||||
|
'gpt-4-turbo-2024-04-09': 128000, # 128K, but may be limited by config.max_model_tokens
|
||||||
|
'gpt-4-turbo': 128000, # 128K, but may be limited by config.max_model_tokens
|
||||||
'claude-instant-1': 100000,
|
'claude-instant-1': 100000,
|
||||||
'claude-2': 100000,
|
'claude-2': 100000,
|
||||||
'command-nightly': 4096,
|
'command-nightly': 4096,
|
||||||
|
@ -15,7 +15,7 @@ class BaseAiHandler(ABC):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
async def chat_completion(self, model: str, system: str, user: str, temperature: float = 0.2):
|
async def chat_completion(self, model: str, system: str, user: str, temperature: float = 0.2, img_path: str = None):
|
||||||
"""
|
"""
|
||||||
This method should be implemented to return a chat completion from the AI model.
|
This method should be implemented to return a chat completion from the AI model.
|
||||||
Args:
|
Args:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import requests
|
||||||
import boto3
|
import boto3
|
||||||
import litellm
|
import litellm
|
||||||
import openai
|
import openai
|
||||||
@ -61,6 +61,9 @@ class LiteLLMAIHandler(BaseAiHandler):
|
|||||||
if get_settings().get("HUGGINGFACE.API_BASE", None) and 'huggingface' in get_settings().config.model:
|
if get_settings().get("HUGGINGFACE.API_BASE", None) and 'huggingface' in get_settings().config.model:
|
||||||
litellm.api_base = get_settings().huggingface.api_base
|
litellm.api_base = get_settings().huggingface.api_base
|
||||||
self.api_base = get_settings().huggingface.api_base
|
self.api_base = get_settings().huggingface.api_base
|
||||||
|
if get_settings().get("OLLAMA.API_BASE", None) :
|
||||||
|
litellm.api_base = get_settings().ollama.api_base
|
||||||
|
self.api_base = get_settings().ollama.api_base
|
||||||
if get_settings().get("HUGGINGFACE.REPITITION_PENALTY", None):
|
if get_settings().get("HUGGINGFACE.REPITITION_PENALTY", None):
|
||||||
self.repetition_penalty = float(get_settings().huggingface.repetition_penalty)
|
self.repetition_penalty = float(get_settings().huggingface.repetition_penalty)
|
||||||
if get_settings().get("VERTEXAI.VERTEX_PROJECT", None):
|
if get_settings().get("VERTEXAI.VERTEX_PROJECT", None):
|
||||||
@ -99,13 +102,27 @@ class LiteLLMAIHandler(BaseAiHandler):
|
|||||||
retry=retry_if_exception_type((openai.APIError, openai.APIConnectionError, openai.Timeout)), # No retry on RateLimitError
|
retry=retry_if_exception_type((openai.APIError, openai.APIConnectionError, openai.Timeout)), # No retry on RateLimitError
|
||||||
stop=stop_after_attempt(OPENAI_RETRIES)
|
stop=stop_after_attempt(OPENAI_RETRIES)
|
||||||
)
|
)
|
||||||
async def chat_completion(self, model: str, system: str, user: str, temperature: float = 0.2):
|
async def chat_completion(self, model: str, system: str, user: str, temperature: float = 0.2, img_path: str = None):
|
||||||
try:
|
try:
|
||||||
resp, finish_reason = None, None
|
resp, finish_reason = None, None
|
||||||
deployment_id = self.deployment_id
|
deployment_id = self.deployment_id
|
||||||
if self.azure:
|
if self.azure:
|
||||||
model = 'azure/' + model
|
model = 'azure/' + model
|
||||||
messages = [{"role": "system", "content": system}, {"role": "user", "content": user}]
|
messages = [{"role": "system", "content": system}, {"role": "user", "content": user}]
|
||||||
|
if img_path:
|
||||||
|
try:
|
||||||
|
# check if the image link is alive
|
||||||
|
r = requests.head(img_path, allow_redirects=True)
|
||||||
|
if r.status_code == 404:
|
||||||
|
error_msg = f"The image link is not [alive](img_path).\nPlease repost the original image as a comment, and send the question again with 'quote reply' (see [instructions](https://pr-agent-docs.codium.ai/tools/ask/#ask-on-images-using-the-pr-code-as-context))."
|
||||||
|
get_logger().error(error_msg)
|
||||||
|
return f"{error_msg}", "error"
|
||||||
|
except Exception as e:
|
||||||
|
get_logger().error(f"Error fetching image: {img_path}", e)
|
||||||
|
return f"Error fetching image: {img_path}", "error"
|
||||||
|
messages[1]["content"] = [{"type": "text", "text": messages[1]["content"]},
|
||||||
|
{"type": "image_url", "image_url": {"url": img_path}}]
|
||||||
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
"model": model,
|
"model": model,
|
||||||
"deployment_id": deployment_id,
|
"deployment_id": deployment_id,
|
||||||
@ -150,4 +167,4 @@ class LiteLLMAIHandler(BaseAiHandler):
|
|||||||
if get_settings().config.verbosity_level >= 2:
|
if get_settings().config.verbosity_level >= 2:
|
||||||
get_logger().info(f"\nAI response:\n{resp}")
|
get_logger().info(f"\nAI response:\n{resp}")
|
||||||
|
|
||||||
return resp, finish_reason
|
return resp, finish_reason
|
||||||
|
@ -9,7 +9,7 @@ from pr_agent.algo.git_patch_processing import convert_to_hunks_with_lines_numbe
|
|||||||
from pr_agent.algo.language_handler import sort_files_by_main_languages
|
from pr_agent.algo.language_handler import sort_files_by_main_languages
|
||||||
from pr_agent.algo.file_filter import filter_ignored
|
from pr_agent.algo.file_filter import filter_ignored
|
||||||
from pr_agent.algo.token_handler import TokenHandler
|
from pr_agent.algo.token_handler import TokenHandler
|
||||||
from pr_agent.algo.utils import get_max_tokens, ModelType
|
from pr_agent.algo.utils import get_max_tokens, clip_tokens, ModelType
|
||||||
from pr_agent.config_loader import get_settings
|
from pr_agent.config_loader import get_settings
|
||||||
from pr_agent.git_providers.git_provider import GitProvider
|
from pr_agent.git_providers.git_provider import GitProvider
|
||||||
from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo
|
from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo
|
||||||
@ -87,22 +87,34 @@ def get_pr_diff(git_provider: GitProvider, token_handler: TokenHandler, model: s
|
|||||||
# if we are over the limit, start pruning
|
# if we are over the limit, start pruning
|
||||||
get_logger().info(f"Tokens: {total_tokens}, total tokens over limit: {get_max_tokens(model)}, "
|
get_logger().info(f"Tokens: {total_tokens}, total tokens over limit: {get_max_tokens(model)}, "
|
||||||
f"pruning diff.")
|
f"pruning diff.")
|
||||||
patches_compressed, modified_file_names, deleted_file_names, added_file_names = \
|
patches_compressed, modified_file_names, deleted_file_names, added_file_names, total_tokens_new = \
|
||||||
pr_generate_compressed_diff(pr_languages, token_handler, model, add_line_numbers_to_hunks)
|
pr_generate_compressed_diff(pr_languages, token_handler, model, add_line_numbers_to_hunks)
|
||||||
|
|
||||||
|
# Insert additional information about added, modified, and deleted files if there is enough space
|
||||||
|
max_tokens = get_max_tokens(model) - OUTPUT_BUFFER_TOKENS_HARD_THRESHOLD
|
||||||
|
curr_token = total_tokens_new # == token_handler.count_tokens(final_diff)+token_handler.prompt_tokens
|
||||||
final_diff = "\n".join(patches_compressed)
|
final_diff = "\n".join(patches_compressed)
|
||||||
if added_file_names:
|
delta_tokens = 10
|
||||||
|
if added_file_names and (max_tokens - curr_token) > delta_tokens:
|
||||||
added_list_str = ADDED_FILES_ + "\n".join(added_file_names)
|
added_list_str = ADDED_FILES_ + "\n".join(added_file_names)
|
||||||
final_diff = final_diff + "\n\n" + added_list_str
|
added_list_str = clip_tokens(added_list_str, max_tokens - curr_token)
|
||||||
if modified_file_names:
|
if added_list_str:
|
||||||
|
final_diff = final_diff + "\n\n" + added_list_str
|
||||||
|
curr_token += token_handler.count_tokens(added_list_str) + 2
|
||||||
|
if modified_file_names and (max_tokens - curr_token) > delta_tokens:
|
||||||
modified_list_str = MORE_MODIFIED_FILES_ + "\n".join(modified_file_names)
|
modified_list_str = MORE_MODIFIED_FILES_ + "\n".join(modified_file_names)
|
||||||
final_diff = final_diff + "\n\n" + modified_list_str
|
modified_list_str = clip_tokens(modified_list_str, max_tokens - curr_token)
|
||||||
if deleted_file_names:
|
if modified_list_str:
|
||||||
|
final_diff = final_diff + "\n\n" + modified_list_str
|
||||||
|
curr_token += token_handler.count_tokens(modified_list_str) + 2
|
||||||
|
if deleted_file_names and (max_tokens - curr_token) > delta_tokens:
|
||||||
deleted_list_str = DELETED_FILES_ + "\n".join(deleted_file_names)
|
deleted_list_str = DELETED_FILES_ + "\n".join(deleted_file_names)
|
||||||
final_diff = final_diff + "\n\n" + deleted_list_str
|
deleted_list_str = clip_tokens(deleted_list_str, max_tokens - curr_token)
|
||||||
|
if deleted_list_str:
|
||||||
|
final_diff = final_diff + "\n\n" + deleted_list_str
|
||||||
try:
|
try:
|
||||||
get_logger().debug(f"After pruning, added_list_str: {added_list_str}, modified_list_str: {modified_list_str}, "
|
get_logger().debug(f"After pruning, added_list_str: {added_list_str}, modified_list_str: {modified_list_str}, "
|
||||||
f"deleted_list_str: {deleted_list_str}")
|
f"deleted_list_str: {deleted_list_str}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
return final_diff
|
return final_diff
|
||||||
@ -149,7 +161,7 @@ def pr_generate_extended_diff(pr_languages: list,
|
|||||||
|
|
||||||
|
|
||||||
def pr_generate_compressed_diff(top_langs: list, token_handler: TokenHandler, model: str,
|
def pr_generate_compressed_diff(top_langs: list, token_handler: TokenHandler, model: str,
|
||||||
convert_hunks_to_line_numbers: bool) -> Tuple[list, list, list, list]:
|
convert_hunks_to_line_numbers: bool) -> Tuple[list, list, list, list, int]:
|
||||||
"""
|
"""
|
||||||
Generate a compressed diff string for a pull request, using diff minimization techniques to reduce the number of
|
Generate a compressed diff string for a pull request, using diff minimization techniques to reduce the number of
|
||||||
tokens used.
|
tokens used.
|
||||||
@ -195,10 +207,11 @@ def pr_generate_compressed_diff(top_langs: list, token_handler: TokenHandler, mo
|
|||||||
patch = handle_patch_deletions(patch, original_file_content_str,
|
patch = handle_patch_deletions(patch, original_file_content_str,
|
||||||
new_file_content_str, file.filename, file.edit_type)
|
new_file_content_str, file.filename, file.edit_type)
|
||||||
if patch is None:
|
if patch is None:
|
||||||
if not deleted_files_list:
|
# if not deleted_files_list:
|
||||||
total_tokens += token_handler.count_tokens(DELETED_FILES_)
|
# total_tokens += token_handler.count_tokens(DELETED_FILES_)
|
||||||
deleted_files_list.append(file.filename)
|
if file.filename not in deleted_files_list:
|
||||||
total_tokens += token_handler.count_tokens(file.filename) + 1
|
deleted_files_list.append(file.filename)
|
||||||
|
# total_tokens += token_handler.count_tokens(file.filename) + 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if convert_hunks_to_line_numbers:
|
if convert_hunks_to_line_numbers:
|
||||||
@ -219,14 +232,17 @@ def pr_generate_compressed_diff(top_langs: list, token_handler: TokenHandler, mo
|
|||||||
if get_settings().config.verbosity_level >= 2:
|
if get_settings().config.verbosity_level >= 2:
|
||||||
get_logger().warning(f"Patch too large, minimizing it, {file.filename}")
|
get_logger().warning(f"Patch too large, minimizing it, {file.filename}")
|
||||||
if file.edit_type == EDIT_TYPE.ADDED:
|
if file.edit_type == EDIT_TYPE.ADDED:
|
||||||
if not added_files_list:
|
# if not added_files_list:
|
||||||
total_tokens += token_handler.count_tokens(ADDED_FILES_)
|
# total_tokens += token_handler.count_tokens(ADDED_FILES_)
|
||||||
added_files_list.append(file.filename)
|
if file.filename not in added_files_list:
|
||||||
|
added_files_list.append(file.filename)
|
||||||
|
# total_tokens += token_handler.count_tokens(file.filename) + 1
|
||||||
else:
|
else:
|
||||||
if not modified_files_list:
|
# if not modified_files_list:
|
||||||
total_tokens += token_handler.count_tokens(MORE_MODIFIED_FILES_)
|
# total_tokens += token_handler.count_tokens(MORE_MODIFIED_FILES_)
|
||||||
modified_files_list.append(file.filename)
|
if file.filename not in modified_files_list:
|
||||||
total_tokens += token_handler.count_tokens(file.filename) + 1
|
modified_files_list.append(file.filename)
|
||||||
|
# total_tokens += token_handler.count_tokens(file.filename) + 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if patch:
|
if patch:
|
||||||
@ -239,7 +255,7 @@ def pr_generate_compressed_diff(top_langs: list, token_handler: TokenHandler, mo
|
|||||||
if get_settings().config.verbosity_level >= 2:
|
if get_settings().config.verbosity_level >= 2:
|
||||||
get_logger().info(f"Tokens: {total_tokens}, last filename: {file.filename}")
|
get_logger().info(f"Tokens: {total_tokens}, last filename: {file.filename}")
|
||||||
|
|
||||||
return patches, modified_files_list, deleted_files_list, added_files_list
|
return patches, modified_files_list, deleted_files_list, added_files_list, total_tokens
|
||||||
|
|
||||||
|
|
||||||
async def retry_with_fallback_models(f: Callable, model_type: ModelType = ModelType.REGULAR):
|
async def retry_with_fallback_models(f: Callable, model_type: ModelType = ModelType.REGULAR):
|
||||||
@ -382,4 +398,4 @@ def get_pr_multi_diffs(git_provider: GitProvider,
|
|||||||
final_diff = "\n".join(patches)
|
final_diff = "\n".join(patches)
|
||||||
final_diff_list.append(final_diff)
|
final_diff_list.append(final_diff)
|
||||||
|
|
||||||
return final_diff_list
|
return final_diff_list
|
@ -1,12 +1,25 @@
|
|||||||
from jinja2 import Environment, StrictUndefined
|
from jinja2 import Environment, StrictUndefined
|
||||||
from tiktoken import encoding_for_model, get_encoding
|
from tiktoken import encoding_for_model, get_encoding
|
||||||
|
|
||||||
from pr_agent.config_loader import get_settings
|
from pr_agent.config_loader import get_settings
|
||||||
|
from threading import Lock
|
||||||
|
|
||||||
|
|
||||||
def get_token_encoder():
|
class TokenEncoder:
|
||||||
return encoding_for_model(get_settings().config.model) if "gpt" in get_settings().config.model else get_encoding(
|
_encoder_instance = None
|
||||||
"cl100k_base")
|
_model = None
|
||||||
|
_lock = Lock() # Create a lock object
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_token_encoder(cls):
|
||||||
|
model = get_settings().config.model
|
||||||
|
if cls._encoder_instance is None or model != cls._model: # Check without acquiring the lock for performance
|
||||||
|
with cls._lock: # Lock acquisition to ensure thread safety
|
||||||
|
if cls._encoder_instance is None or model != cls._model:
|
||||||
|
cls._model = model
|
||||||
|
cls._encoder_instance = encoding_for_model(cls._model) if "gpt" in cls._model else get_encoding(
|
||||||
|
"cl100k_base")
|
||||||
|
return cls._encoder_instance
|
||||||
|
|
||||||
|
|
||||||
class TokenHandler:
|
class TokenHandler:
|
||||||
"""
|
"""
|
||||||
@ -31,7 +44,7 @@ class TokenHandler:
|
|||||||
- system: The system string.
|
- system: The system string.
|
||||||
- user: The user string.
|
- user: The user string.
|
||||||
"""
|
"""
|
||||||
self.encoder = get_token_encoder()
|
self.encoder = TokenEncoder.get_token_encoder()
|
||||||
if pr is not None:
|
if pr is not None:
|
||||||
self.prompt_tokens = self._get_system_user_tokens(pr, self.encoder, vars, system, user)
|
self.prompt_tokens = self._get_system_user_tokens(pr, self.encoder, vars, system, user)
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import difflib
|
import difflib
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import textwrap
|
import textwrap
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@ -12,7 +13,7 @@ import yaml
|
|||||||
from starlette_context import context
|
from starlette_context import context
|
||||||
|
|
||||||
from pr_agent.algo import MAX_TOKENS
|
from pr_agent.algo import MAX_TOKENS
|
||||||
from pr_agent.algo.token_handler import get_token_encoder
|
from pr_agent.algo.token_handler import TokenEncoder
|
||||||
from pr_agent.config_loader import get_settings, global_settings
|
from pr_agent.config_loader import get_settings, global_settings
|
||||||
from pr_agent.algo.types import FilePatchInfo
|
from pr_agent.algo.types import FilePatchInfo
|
||||||
from pr_agent.log import get_logger
|
from pr_agent.log import get_logger
|
||||||
@ -566,7 +567,7 @@ def clip_tokens(text: str, max_tokens: int, add_three_dots=True) -> str:
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
try:
|
try:
|
||||||
encoder = get_token_encoder()
|
encoder = TokenEncoder.get_token_encoder()
|
||||||
num_input_tokens = len(encoder.encode(text))
|
num_input_tokens = len(encoder.encode(text))
|
||||||
if num_input_tokens <= max_tokens:
|
if num_input_tokens <= max_tokens:
|
||||||
return text
|
return text
|
||||||
@ -575,7 +576,7 @@ def clip_tokens(text: str, max_tokens: int, add_three_dots=True) -> str:
|
|||||||
num_output_chars = int(chars_per_token * max_tokens)
|
num_output_chars = int(chars_per_token * max_tokens)
|
||||||
clipped_text = text[:num_output_chars]
|
clipped_text = text[:num_output_chars]
|
||||||
if add_three_dots:
|
if add_three_dots:
|
||||||
clipped_text += "...(truncated)"
|
clipped_text += "\n...(truncated)"
|
||||||
return clipped_text
|
return clipped_text
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
get_logger().warning(f"Failed to clip tokens: {e}")
|
get_logger().warning(f"Failed to clip tokens: {e}")
|
||||||
@ -661,3 +662,15 @@ def find_line_number_of_relevant_line_in_file(diff_files: List[FilePatchInfo],
|
|||||||
absolute_position = start2 + delta - 1
|
absolute_position = start2 + delta - 1
|
||||||
break
|
break
|
||||||
return position, absolute_position
|
return position, absolute_position
|
||||||
|
|
||||||
|
def github_action_output(output_data: dict, key_name: str):
|
||||||
|
try:
|
||||||
|
if not get_settings().get('github_action_config.enable_output', False):
|
||||||
|
return
|
||||||
|
|
||||||
|
key_data = output_data.get(key_name, {})
|
||||||
|
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
||||||
|
print(f"{key_name}={json.dumps(key_data, indent=None, ensure_ascii=False)}", file=fh)
|
||||||
|
except Exception as e:
|
||||||
|
get_logger().error(f"Failed to write to GitHub Action output: {e}")
|
||||||
|
return
|
@ -10,7 +10,7 @@ from ..algo.utils import load_large_diff
|
|||||||
from .git_provider import GitProvider
|
from .git_provider import GitProvider
|
||||||
from ..config_loader import get_settings
|
from ..config_loader import get_settings
|
||||||
from ..log import get_logger
|
from ..log import get_logger
|
||||||
|
from pr_agent.algo.language_handler import is_valid_file
|
||||||
|
|
||||||
class PullRequestCCMimic:
|
class PullRequestCCMimic:
|
||||||
"""
|
"""
|
||||||
|
@ -745,22 +745,4 @@ class GithubProvider(GitProvider):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def calc_pr_statistics(self, pull_request_data: dict):
|
def calc_pr_statistics(self, pull_request_data: dict):
|
||||||
try:
|
return {}
|
||||||
out = {}
|
|
||||||
from datetime import datetime
|
|
||||||
created_at = pull_request_data['created_at']
|
|
||||||
closed_at = pull_request_data['closed_at']
|
|
||||||
closed_at_datetime = datetime.strptime(closed_at, "%Y-%m-%dT%H:%M:%SZ")
|
|
||||||
created_at_datetime = datetime.strptime(created_at, "%Y-%m-%dT%H:%M:%SZ")
|
|
||||||
difference = closed_at_datetime - created_at_datetime
|
|
||||||
out['hours'] = difference.total_seconds() / 3600
|
|
||||||
out['commits'] = pull_request_data['commits']
|
|
||||||
out['comments'] = pull_request_data['comments']
|
|
||||||
out['review_comments'] = pull_request_data['review_comments']
|
|
||||||
out['changed_files'] = pull_request_data['changed_files']
|
|
||||||
out['additions'] = pull_request_data['additions']
|
|
||||||
out['deletions'] = pull_request_data['deletions']
|
|
||||||
except Exception as e:
|
|
||||||
get_logger().exception(f"Failed to calculate PR statistics, error: {e}")
|
|
||||||
return {}
|
|
||||||
return out
|
|
||||||
|
@ -46,19 +46,22 @@ async def run_action():
|
|||||||
if not GITHUB_EVENT_PATH:
|
if not GITHUB_EVENT_PATH:
|
||||||
print("GITHUB_EVENT_PATH not set")
|
print("GITHUB_EVENT_PATH not set")
|
||||||
return
|
return
|
||||||
if not OPENAI_KEY:
|
|
||||||
print("OPENAI_KEY not set")
|
|
||||||
return
|
|
||||||
if not GITHUB_TOKEN:
|
if not GITHUB_TOKEN:
|
||||||
print("GITHUB_TOKEN not set")
|
print("GITHUB_TOKEN not set")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Set the environment variables in the settings
|
# Set the environment variables in the settings
|
||||||
get_settings().set("OPENAI.KEY", OPENAI_KEY)
|
if OPENAI_KEY:
|
||||||
|
get_settings().set("OPENAI.KEY", OPENAI_KEY)
|
||||||
|
else:
|
||||||
|
# Might not be set if the user is using models not from OpenAI
|
||||||
|
print("OPENAI_KEY not set")
|
||||||
if OPENAI_ORG:
|
if OPENAI_ORG:
|
||||||
get_settings().set("OPENAI.ORG", OPENAI_ORG)
|
get_settings().set("OPENAI.ORG", OPENAI_ORG)
|
||||||
get_settings().set("GITHUB.USER_TOKEN", GITHUB_TOKEN)
|
get_settings().set("GITHUB.USER_TOKEN", GITHUB_TOKEN)
|
||||||
get_settings().set("GITHUB.DEPLOYMENT_TYPE", "user")
|
get_settings().set("GITHUB.DEPLOYMENT_TYPE", "user")
|
||||||
|
enable_output = get_setting_or_env("GITHUB_ACTION_CONFIG.ENABLE_OUTPUT", True)
|
||||||
|
get_settings().set("GITHUB_ACTION_CONFIG.ENABLE_OUTPUT", enable_output)
|
||||||
|
|
||||||
# Load the event payload
|
# Load the event payload
|
||||||
try:
|
try:
|
||||||
@ -101,6 +104,8 @@ async def run_action():
|
|||||||
await PRReviewer(pr_url).run()
|
await PRReviewer(pr_url).run()
|
||||||
if auto_improve is None or is_true(auto_improve):
|
if auto_improve is None or is_true(auto_improve):
|
||||||
await PRCodeSuggestions(pr_url).run()
|
await PRCodeSuggestions(pr_url).run()
|
||||||
|
else:
|
||||||
|
get_logger().info(f"Skipping action: {action}")
|
||||||
|
|
||||||
# Handle issue comment event
|
# Handle issue comment event
|
||||||
elif GITHUB_EVENT_NAME == "issue_comment" or GITHUB_EVENT_NAME == "pull_request_review_comment":
|
elif GITHUB_EVENT_NAME == "issue_comment" or GITHUB_EVENT_NAME == "pull_request_review_comment":
|
||||||
|
@ -86,8 +86,13 @@ async def handle_comments_on_pr(body: Dict[str, Any],
|
|||||||
return {}
|
return {}
|
||||||
comment_body = body.get("comment", {}).get("body")
|
comment_body = body.get("comment", {}).get("body")
|
||||||
if comment_body and isinstance(comment_body, str) and not comment_body.lstrip().startswith("/"):
|
if comment_body and isinstance(comment_body, str) and not comment_body.lstrip().startswith("/"):
|
||||||
get_logger().info("Ignoring comment not starting with /")
|
if '/ask' in comment_body and comment_body.strip().startswith('> ![image]'):
|
||||||
return {}
|
comment_body_split = comment_body.split('/ask')
|
||||||
|
comment_body = '/ask' + comment_body_split[1] +' \n' +comment_body_split[0].strip().lstrip('>')
|
||||||
|
get_logger().info(f"Reformatting comment_body so command is at the beginning: {comment_body}")
|
||||||
|
else:
|
||||||
|
get_logger().info("Ignoring comment not starting with /")
|
||||||
|
return {}
|
||||||
disable_eyes = False
|
disable_eyes = False
|
||||||
if "issue" in body and "pull_request" in body["issue"] and "url" in body["issue"]["pull_request"]:
|
if "issue" in body and "pull_request" in body["issue"] and "url" in body["issue"]["pull_request"]:
|
||||||
api_url = body["issue"]["pull_request"]["url"]
|
api_url = body["issue"]["pull_request"]["url"]
|
||||||
|
@ -128,7 +128,7 @@ Be specific, clear, and concise in the instructions. With extra instructions, yo
|
|||||||
Examples for extra instructions:
|
Examples for extra instructions:
|
||||||
```
|
```
|
||||||
[pr_description]
|
[pr_description]
|
||||||
extra_instructions="""
|
extra_instructions="""\
|
||||||
- The PR title should be in the format: '<PR type>: <title>'
|
- The PR title should be in the format: '<PR type>: <title>'
|
||||||
- The title should be short and concise (up to 10 words)
|
- The title should be short and concise (up to 10 words)
|
||||||
- ...
|
- ...
|
||||||
@ -160,16 +160,17 @@ It can be invoked manually by commenting on any PR:
|
|||||||
/ask "..."
|
/ask "..."
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the tool does not have "memory" of previous questions, and answers each question independently.
|
Note that the tool does not have "memory" of previous questions, and answers each question independently.
|
||||||
|
You can ask questions about the entire PR, about specific code lines, or about an image related to the PR code changes.
|
||||||
"""
|
"""
|
||||||
output += "\n\n<table>"
|
# output += "\n\n<table>"
|
||||||
|
#
|
||||||
# general
|
# # # general
|
||||||
output += "\n\n<tr><td><details> <summary><strong> More PR-Agent commands</strong></summary><hr> \n\n"
|
# # output += "\n\n<tr><td><details> <summary><strong> More PR-Agent commands</strong></summary><hr> \n\n"
|
||||||
output += HelpMessage.get_general_bot_help_text()
|
# # output += HelpMessage.get_general_bot_help_text()
|
||||||
output += "\n\n</details></td></tr>\n\n"
|
# # output += "\n\n</details></td></tr>\n\n"
|
||||||
|
#
|
||||||
output += "</table>"
|
# output += "</table>"
|
||||||
|
|
||||||
output += f"\n\nSee the [ask usage](https://pr-agent-docs.codium.ai/tools/ask/) page for a comprehensive guide on using this tool.\n\n"
|
output += f"\n\nSee the [ask usage](https://pr-agent-docs.codium.ai/tools/ask/) page for a comprehensive guide on using this tool.\n\n"
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[config]
|
[config]
|
||||||
model="gpt-4" # "gpt-4-0125-preview"
|
model="gpt-4-turbo-2024-04-09"
|
||||||
model_turbo="gpt-4-0125-preview"
|
model_turbo="gpt-4-turbo-2024-04-09"
|
||||||
fallback_models=["gpt-3.5-turbo-16k"]
|
fallback_models=["gpt-4-0125-preview"]
|
||||||
git_provider="github"
|
git_provider="github"
|
||||||
publish_output=true
|
publish_output=true
|
||||||
publish_output_progress=true
|
publish_output_progress=true
|
||||||
@ -61,6 +61,9 @@ enable_pr_type=true
|
|||||||
disable_final_update_message = false
|
disable_final_update_message = false
|
||||||
enable_help_text=false
|
enable_help_text=false
|
||||||
enable_help_comment=true
|
enable_help_comment=true
|
||||||
|
# describe as comment
|
||||||
|
publish_description_as_comment=false
|
||||||
|
publish_description_as_comment_persistent=true
|
||||||
## changes walkthrough section
|
## changes walkthrough section
|
||||||
enable_semantic_files_types=true
|
enable_semantic_files_types=true
|
||||||
collapsible_file_list='adaptive' # true, false, 'adaptive'
|
collapsible_file_list='adaptive' # true, false, 'adaptive'
|
||||||
@ -110,6 +113,11 @@ file = "" # in case there are several components with the same name
|
|||||||
class_name = "" # in case there are several methods with the same name in the same file, you can specify the relevant class name
|
class_name = "" # in case there are several methods with the same name in the same file, you can specify the relevant class name
|
||||||
enable_help_text=true
|
enable_help_text=true
|
||||||
|
|
||||||
|
[pr_improve_component] # /improve_component #
|
||||||
|
num_code_suggestions=4
|
||||||
|
extra_instructions = ""
|
||||||
|
file = "" # in case there are several components with the same name, you can specify the relevant file
|
||||||
|
class_name = ""
|
||||||
|
|
||||||
[checks] # /checks (pro feature) #
|
[checks] # /checks (pro feature) #
|
||||||
enable_auto_checks_feedback=true
|
enable_auto_checks_feedback=true
|
||||||
@ -133,6 +141,7 @@ try_fix_invalid_inline_comments = true
|
|||||||
# auto_review = true # set as env var in .github/workflows/pr-agent.yaml
|
# auto_review = true # set as env var in .github/workflows/pr-agent.yaml
|
||||||
# auto_describe = true # set as env var in .github/workflows/pr-agent.yaml
|
# auto_describe = true # set as env var in .github/workflows/pr-agent.yaml
|
||||||
# auto_improve = true # set as env var in .github/workflows/pr-agent.yaml
|
# auto_improve = true # set as env var in .github/workflows/pr-agent.yaml
|
||||||
|
# enable_output = true # set as env var in .github/workflows/pr-agent.yaml
|
||||||
|
|
||||||
[github_app]
|
[github_app]
|
||||||
# these toggles allows running the github app from custom deployments
|
# these toggles allows running the github app from custom deployments
|
||||||
|
@ -76,7 +76,7 @@ class PRCodeSuggestions:
|
|||||||
relevant_configs = {'pr_code_suggestions': dict(get_settings().pr_code_suggestions),
|
relevant_configs = {'pr_code_suggestions': dict(get_settings().pr_code_suggestions),
|
||||||
'config': dict(get_settings().config)}
|
'config': dict(get_settings().config)}
|
||||||
get_logger().debug("Relevant configs", artifacts=relevant_configs)
|
get_logger().debug("Relevant configs", artifacts=relevant_configs)
|
||||||
if get_settings().config.publish_output:
|
if get_settings().config.publish_output and get_settings().config.publish_output_progress:
|
||||||
if self.git_provider.is_supported("gfm_markdown"):
|
if self.git_provider.is_supported("gfm_markdown"):
|
||||||
self.progress_response = self.git_provider.publish_comment(self.progress)
|
self.progress_response = self.git_provider.publish_comment(self.progress)
|
||||||
else:
|
else:
|
||||||
@ -196,24 +196,31 @@ class PRCodeSuggestions:
|
|||||||
suggestion_list = []
|
suggestion_list = []
|
||||||
one_sentence_summary_list = []
|
one_sentence_summary_list = []
|
||||||
for i, suggestion in enumerate(data['code_suggestions']):
|
for i, suggestion in enumerate(data['code_suggestions']):
|
||||||
if get_settings().pr_code_suggestions.summarize:
|
try:
|
||||||
if not suggestion or 'one_sentence_summary' not in suggestion or 'label' not in suggestion or 'relevant_file' not in suggestion:
|
|
||||||
get_logger().debug(f"Skipping suggestion {i + 1}, because it is invalid: {suggestion}")
|
|
||||||
continue
|
|
||||||
|
|
||||||
if suggestion['one_sentence_summary'] in one_sentence_summary_list:
|
|
||||||
get_logger().debug(f"Skipping suggestion {i + 1}, because it is a duplicate: {suggestion}")
|
|
||||||
continue
|
|
||||||
|
|
||||||
if ('existing_code' in suggestion) and ('improved_code' in suggestion) and (
|
|
||||||
suggestion['existing_code'] != suggestion['improved_code']):
|
|
||||||
suggestion = self._truncate_if_needed(suggestion)
|
|
||||||
if get_settings().pr_code_suggestions.summarize:
|
if get_settings().pr_code_suggestions.summarize:
|
||||||
one_sentence_summary_list.append(suggestion['one_sentence_summary'])
|
if not suggestion or 'one_sentence_summary' not in suggestion or 'label' not in suggestion or 'relevant_file' not in suggestion:
|
||||||
suggestion_list.append(suggestion)
|
get_logger().debug(f"Skipping suggestion {i + 1}, because it is invalid: {suggestion}")
|
||||||
else:
|
continue
|
||||||
get_logger().debug(
|
|
||||||
f"Skipping suggestion {i + 1}, because existing code is equal to improved code {suggestion['existing_code']}")
|
if suggestion['one_sentence_summary'] in one_sentence_summary_list:
|
||||||
|
get_logger().debug(f"Skipping suggestion {i + 1}, because it is a duplicate: {suggestion}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if 'const' in suggestion['suggestion_content'] and 'instead' in suggestion['suggestion_content'] and 'let' in suggestion['suggestion_content']:
|
||||||
|
get_logger().debug(f"Skipping suggestion {i + 1}, because it uses 'const instead let': {suggestion}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if ('existing_code' in suggestion) and ('improved_code' in suggestion) and (
|
||||||
|
suggestion['existing_code'] != suggestion['improved_code']):
|
||||||
|
suggestion = self._truncate_if_needed(suggestion)
|
||||||
|
if get_settings().pr_code_suggestions.summarize:
|
||||||
|
one_sentence_summary_list.append(suggestion['one_sentence_summary'])
|
||||||
|
suggestion_list.append(suggestion)
|
||||||
|
else:
|
||||||
|
get_logger().debug(
|
||||||
|
f"Skipping suggestion {i + 1}, because existing code is equal to improved code {suggestion['existing_code']}")
|
||||||
|
except Exception as e:
|
||||||
|
get_logger().error(f"Error processing suggestion {i + 1}: {suggestion}, error: {e}")
|
||||||
data['code_suggestions'] = suggestion_list
|
data['code_suggestions'] = suggestion_list
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
@ -132,7 +132,14 @@ class PRDescription:
|
|||||||
# publish description
|
# publish description
|
||||||
if get_settings().pr_description.publish_description_as_comment:
|
if get_settings().pr_description.publish_description_as_comment:
|
||||||
full_markdown_description = f"## Title\n\n{pr_title}\n\n___\n{pr_body}"
|
full_markdown_description = f"## Title\n\n{pr_title}\n\n___\n{pr_body}"
|
||||||
self.git_provider.publish_comment(full_markdown_description)
|
if get_settings().pr_description.publish_description_as_comment_persistent:
|
||||||
|
self.git_provider.publish_persistent_comment(full_markdown_description,
|
||||||
|
initial_header="## Title",
|
||||||
|
update_header=True,
|
||||||
|
name="describe",
|
||||||
|
final_update_message=False, )
|
||||||
|
else:
|
||||||
|
self.git_provider.publish_comment(full_markdown_description)
|
||||||
else:
|
else:
|
||||||
self.git_provider.publish_description(pr_title, pr_body)
|
self.git_provider.publish_description(pr_title, pr_body)
|
||||||
|
|
||||||
|
@ -27,12 +27,13 @@ class PRHelpMessage:
|
|||||||
tool_names.append(f"[DESCRIBE]({base_path}/describe/)")
|
tool_names.append(f"[DESCRIBE]({base_path}/describe/)")
|
||||||
tool_names.append(f"[REVIEW]({base_path}/review/)")
|
tool_names.append(f"[REVIEW]({base_path}/review/)")
|
||||||
tool_names.append(f"[IMPROVE]({base_path}/improve/)")
|
tool_names.append(f"[IMPROVE]({base_path}/improve/)")
|
||||||
tool_names.append(f"[ANALYZE]({base_path}/analyze/) 💎")
|
|
||||||
tool_names.append(f"[UPDATE CHANGELOG]({base_path}/update_changelog/)")
|
tool_names.append(f"[UPDATE CHANGELOG]({base_path}/update_changelog/)")
|
||||||
tool_names.append(f"[ADD DOCUMENTATION]({base_path}/documentation/) 💎")
|
tool_names.append(f"[ADD DOCS]({base_path}/documentation/) 💎")
|
||||||
tool_names.append(f"[ASK]({base_path}/ask/)")
|
|
||||||
tool_names.append(f"[GENERATE CUSTOM LABELS]({base_path}/custom_labels/)")
|
|
||||||
tool_names.append(f"[TEST]({base_path}/test/) 💎")
|
tool_names.append(f"[TEST]({base_path}/test/) 💎")
|
||||||
|
tool_names.append(f"[IMPROVE COMPONENT]({base_path}/improve_component/) 💎")
|
||||||
|
tool_names.append(f"[ANALYZE]({base_path}/analyze/) 💎")
|
||||||
|
tool_names.append(f"[ASK]({base_path}/ask/)")
|
||||||
|
tool_names.append(f"[GENERATE CUSTOM LABELS]({base_path}/custom_labels/) 💎")
|
||||||
tool_names.append(f"[CI FEEDBACK]({base_path}/ci_feedback/) 💎")
|
tool_names.append(f"[CI FEEDBACK]({base_path}/ci_feedback/) 💎")
|
||||||
tool_names.append(f"[CUSTOM SUGGESTIONS]({base_path}/custom_suggestions/) 💎")
|
tool_names.append(f"[CUSTOM SUGGESTIONS]({base_path}/custom_suggestions/) 💎")
|
||||||
tool_names.append(f"[SIMILAR ISSUE]({base_path}/similar_issues/)")
|
tool_names.append(f"[SIMILAR ISSUE]({base_path}/similar_issues/)")
|
||||||
@ -40,27 +41,29 @@ class PRHelpMessage:
|
|||||||
descriptions = []
|
descriptions = []
|
||||||
descriptions.append("Generates PR description - title, type, summary, code walkthrough and labels")
|
descriptions.append("Generates PR description - title, type, summary, code walkthrough and labels")
|
||||||
descriptions.append("Adjustable feedback about the PR, possible issues, security concerns, review effort and more")
|
descriptions.append("Adjustable feedback about the PR, possible issues, security concerns, review effort and more")
|
||||||
descriptions.append("Code suggestions for improving the PR.")
|
descriptions.append("Code suggestions for improving the PR")
|
||||||
descriptions.append("Identifies code components that changed in the PR, and enables to interactively generate tests, docs, and code suggestions for each component.")
|
descriptions.append("Automatically updates the changelog")
|
||||||
descriptions.append("Automatically updates the changelog.")
|
descriptions.append("Generates documentation to methods/functions/classes that changed in the PR")
|
||||||
descriptions.append("Generates documentation to methods/functions/classes that changed in the PR.")
|
descriptions.append("Generates unit tests for a specific component, based on the PR code change")
|
||||||
descriptions.append("Answering free-text questions about the PR.")
|
descriptions.append("Code suggestions for a specific component that changed in the PR")
|
||||||
|
descriptions.append("Identifies code components that changed in the PR, and enables to interactively generate tests, docs, and code suggestions for each component")
|
||||||
|
descriptions.append("Answering free-text questions about the PR")
|
||||||
descriptions.append("Generates custom labels for the PR, based on specific guidelines defined by the user")
|
descriptions.append("Generates custom labels for the PR, based on specific guidelines defined by the user")
|
||||||
descriptions.append("Generates unit tests for a specific component, based on the PR code change.")
|
descriptions.append("Generates feedback and analysis for a failed CI job")
|
||||||
descriptions.append("Generates feedback and analysis for a failed CI job.")
|
descriptions.append("Generates custom suggestions for improving the PR code, based only on specific guidelines defined by the user")
|
||||||
descriptions.append("Generates custom suggestions for improving the PR code, based on specific guidelines defined by the user.")
|
descriptions.append("Automatically retrieves and presents similar issues")
|
||||||
descriptions.append("Automatically retrieves and presents similar issues.")
|
|
||||||
|
|
||||||
commands =[]
|
commands =[]
|
||||||
commands.append("`/describe`")
|
commands.append("`/describe`")
|
||||||
commands.append("`/review`")
|
commands.append("`/review`")
|
||||||
commands.append("`/improve`")
|
commands.append("`/improve`")
|
||||||
commands.append("`/analyze`")
|
|
||||||
commands.append("`/update_changelog`")
|
commands.append("`/update_changelog`")
|
||||||
commands.append("`/add_docs`")
|
commands.append("`/add_docs`")
|
||||||
|
commands.append("`/test`")
|
||||||
|
commands.append("`/improve_component`")
|
||||||
|
commands.append("`/analyze`")
|
||||||
commands.append("`/ask`")
|
commands.append("`/ask`")
|
||||||
commands.append("`/generate_labels`")
|
commands.append("`/generate_labels`")
|
||||||
commands.append("`/test`")
|
|
||||||
commands.append("`/checks`")
|
commands.append("`/checks`")
|
||||||
commands.append("`/custom_suggestions`")
|
commands.append("`/custom_suggestions`")
|
||||||
commands.append("`/similar_issue`")
|
commands.append("`/similar_issue`")
|
||||||
@ -69,9 +72,13 @@ class PRHelpMessage:
|
|||||||
checkbox_list.append(" - [ ] Run <!-- /describe -->")
|
checkbox_list.append(" - [ ] Run <!-- /describe -->")
|
||||||
checkbox_list.append(" - [ ] Run <!-- /review -->")
|
checkbox_list.append(" - [ ] Run <!-- /review -->")
|
||||||
checkbox_list.append(" - [ ] Run <!-- /improve -->")
|
checkbox_list.append(" - [ ] Run <!-- /improve -->")
|
||||||
checkbox_list.append(" - [ ] Run <!-- /analyze -->")
|
|
||||||
checkbox_list.append(" - [ ] Run <!-- /update_changelog -->")
|
checkbox_list.append(" - [ ] Run <!-- /update_changelog -->")
|
||||||
checkbox_list.append(" - [ ] Run <!-- /add_docs -->")
|
checkbox_list.append(" - [ ] Run <!-- /add_docs -->")
|
||||||
|
checkbox_list.append(" - [ ] Run <!-- /test -->")
|
||||||
|
checkbox_list.append(" - [ ] Run <!-- /improve_component -->")
|
||||||
|
checkbox_list.append(" - [ ] Run <!-- /analyze -->")
|
||||||
|
checkbox_list.append("[*]")
|
||||||
|
checkbox_list.append("[*]")
|
||||||
checkbox_list.append("[*]")
|
checkbox_list.append("[*]")
|
||||||
checkbox_list.append("[*]")
|
checkbox_list.append("[*]")
|
||||||
checkbox_list.append("[*]")
|
checkbox_list.append("[*]")
|
||||||
@ -80,16 +87,16 @@ class PRHelpMessage:
|
|||||||
checkbox_list.append("[*]")
|
checkbox_list.append("[*]")
|
||||||
|
|
||||||
if isinstance(self.git_provider, GithubProvider):
|
if isinstance(self.git_provider, GithubProvider):
|
||||||
pr_comment += f"<table><tr align='center'><th align='center'>Tool</th><th align='center'>Description</th><th align='center'>Invoke Interactively :gem:</th></tr>"
|
pr_comment += f"<table><tr align='left'><th align='left'>Tool</th><th align='left'>Description</th><th align='left'>Trigger Interactively :gem:</th></tr>"
|
||||||
for i in range(len(tool_names)):
|
for i in range(len(tool_names)):
|
||||||
pr_comment += f"\n<tr><td align='center'>\n\n<strong>{tool_names[i]}</strong></td>\n<td>{descriptions[i]}</td>\n<td>\n\n{checkbox_list[i]}\n</td></tr>"
|
pr_comment += f"\n<tr><td align='left'>\n\n<strong>{tool_names[i]}</strong></td>\n<td>{descriptions[i]}</td>\n<td>\n\n{checkbox_list[i]}\n</td></tr>"
|
||||||
pr_comment += "</table>\n\n"
|
pr_comment += "</table>\n\n"
|
||||||
pr_comment += f"""\n\n(1) Note that each tool be [triggered automatically](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools-for-pr-actions) when a new PR is opened, or called manually by [commenting on a PR](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#online-usage)."""
|
pr_comment += f"""\n\n(1) Note that each tool be [triggered automatically](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#github-app-automatic-tools-for-pr-actions) when a new PR is opened, or called manually by [commenting on a PR](https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#online-usage)."""
|
||||||
pr_comment += f"""\n\n(2) Tools marked with [*] require additional parameters to be passed. For example, to invoke the `/ask` tool, you need to comment on a PR: `/ask "<question content>"`. See the relevant documentation for each tool for more details."""
|
pr_comment += f"""\n\n(2) Tools marked with [*] require additional parameters to be passed. For example, to invoke the `/ask` tool, you need to comment on a PR: `/ask "<question content>"`. See the relevant documentation for each tool for more details."""
|
||||||
else:
|
else:
|
||||||
pr_comment += f"<table><tr align='center'><th align='center'>Tool</th><th align='left'>Command</th><th align='left'>Description</th></tr>"
|
pr_comment += f"<table><tr align='left'><th align='left'>Tool</th><th align='left'>Command</th><th align='left'>Description</th></tr>"
|
||||||
for i in range(len(tool_names)):
|
for i in range(len(tool_names)):
|
||||||
pr_comment += f"\n<tr><td align='center'>\n\n<strong>{tool_names[i]}</strong></td><td>{commands[i]}</td><td>{descriptions[i]}</td></tr>"
|
pr_comment += f"\n<tr><td align='left'>\n\n<strong>{tool_names[i]}</strong></td><td>{commands[i]}</td><td>{descriptions[i]}</td></tr>"
|
||||||
pr_comment += "</table>\n\n"
|
pr_comment += "</table>\n\n"
|
||||||
pr_comment += f"""\n\nNote that each tool be [invoked automatically](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/) when a new PR is opened, or called manually by [commenting on a PR](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/#online-usage)."""
|
pr_comment += f"""\n\nNote that each tool be [invoked automatically](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/) when a new PR is opened, or called manually by [commenting on a PR](https://pr-agent-docs.codium.ai/usage-guide/automations_and_usage/#online-usage)."""
|
||||||
if get_settings().config.publish_output:
|
if get_settings().config.publish_output:
|
||||||
|
@ -56,6 +56,12 @@ class PRQuestions:
|
|||||||
get_logger().debug("Relevant configs", artifacts=relevant_configs)
|
get_logger().debug("Relevant configs", artifacts=relevant_configs)
|
||||||
if get_settings().config.publish_output:
|
if get_settings().config.publish_output:
|
||||||
self.git_provider.publish_comment("Preparing answer...", is_temporary=True)
|
self.git_provider.publish_comment("Preparing answer...", is_temporary=True)
|
||||||
|
|
||||||
|
# identify image
|
||||||
|
img_path = self.idenfity_image_in_comment()
|
||||||
|
if img_path:
|
||||||
|
get_logger().debug(f"Image path identified", artifact=img_path)
|
||||||
|
|
||||||
await retry_with_fallback_models(self._prepare_prediction)
|
await retry_with_fallback_models(self._prepare_prediction)
|
||||||
|
|
||||||
pr_comment = self._prepare_pr_answer()
|
pr_comment = self._prepare_pr_answer()
|
||||||
@ -71,6 +77,19 @@ class PRQuestions:
|
|||||||
self.git_provider.remove_initial_comment()
|
self.git_provider.remove_initial_comment()
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def idenfity_image_in_comment(self):
|
||||||
|
img_path = ''
|
||||||
|
if '![image]' in self.question_str:
|
||||||
|
# assuming structure:
|
||||||
|
# /ask question ... > 
|
||||||
|
img_path = self.question_str.split('![image]')[1].strip().strip('()')
|
||||||
|
self.vars['img_path'] = img_path
|
||||||
|
elif 'https://' in self.question_str and ('.png' in self.question_str or 'jpg' in self.question_str): # direct image link
|
||||||
|
# include https:// in the image path
|
||||||
|
img_path = 'https://' + self.question_str.split('https://')[1]
|
||||||
|
self.vars['img_path'] = img_path
|
||||||
|
return img_path
|
||||||
|
|
||||||
async def _prepare_prediction(self, model: str):
|
async def _prepare_prediction(self, model: str):
|
||||||
self.patches_diff = get_pr_diff(self.git_provider, self.token_handler, model)
|
self.patches_diff = get_pr_diff(self.git_provider, self.token_handler, model)
|
||||||
if self.patches_diff:
|
if self.patches_diff:
|
||||||
@ -86,8 +105,14 @@ class PRQuestions:
|
|||||||
environment = Environment(undefined=StrictUndefined)
|
environment = Environment(undefined=StrictUndefined)
|
||||||
system_prompt = environment.from_string(get_settings().pr_questions_prompt.system).render(variables)
|
system_prompt = environment.from_string(get_settings().pr_questions_prompt.system).render(variables)
|
||||||
user_prompt = environment.from_string(get_settings().pr_questions_prompt.user).render(variables)
|
user_prompt = environment.from_string(get_settings().pr_questions_prompt.user).render(variables)
|
||||||
response, finish_reason = await self.ai_handler.chat_completion(model=model, temperature=0.2,
|
if 'img_path' in variables:
|
||||||
system=system_prompt, user=user_prompt)
|
img_path = self.vars['img_path']
|
||||||
|
response, finish_reason = await self.ai_handler.chat_completion(model=model, temperature=0.2,
|
||||||
|
system=system_prompt, user=user_prompt,
|
||||||
|
img_path=img_path)
|
||||||
|
else:
|
||||||
|
response, finish_reason = await self.ai_handler.chat_completion(model=model, temperature=0.2,
|
||||||
|
system=system_prompt, user=user_prompt)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def _prepare_pr_answer(self) -> str:
|
def _prepare_pr_answer(self) -> str:
|
||||||
|
@ -8,7 +8,7 @@ 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.ai_handlers.litellm_ai_handler import LiteLLMAIHandler
|
||||||
from pr_agent.algo.pr_processing import get_pr_diff, retry_with_fallback_models
|
from pr_agent.algo.pr_processing import get_pr_diff, retry_with_fallback_models
|
||||||
from pr_agent.algo.token_handler import TokenHandler
|
from pr_agent.algo.token_handler import TokenHandler
|
||||||
from pr_agent.algo.utils import convert_to_markdown, load_yaml, ModelType
|
from pr_agent.algo.utils import convert_to_markdown, github_action_output, load_yaml, ModelType
|
||||||
from pr_agent.config_loader import get_settings
|
from pr_agent.config_loader import get_settings
|
||||||
from pr_agent.git_providers import get_git_provider
|
from pr_agent.git_providers import get_git_provider
|
||||||
from pr_agent.git_providers.git_provider import IncrementalPR, get_main_pr_language
|
from pr_agent.git_providers.git_provider import IncrementalPR, get_main_pr_language
|
||||||
@ -192,6 +192,7 @@ class PRReviewer:
|
|||||||
data = load_yaml(self.prediction.strip(),
|
data = load_yaml(self.prediction.strip(),
|
||||||
keys_fix_yaml=["estimated_effort_to_review_[1-5]:", "security_concerns:", "possible_issues:",
|
keys_fix_yaml=["estimated_effort_to_review_[1-5]:", "security_concerns:", "possible_issues:",
|
||||||
"relevant_file:", "relevant_line:", "suggestion:"])
|
"relevant_file:", "relevant_line:", "suggestion:"])
|
||||||
|
github_action_output(data, 'review')
|
||||||
|
|
||||||
if 'code_feedback' in data:
|
if 'code_feedback' in data:
|
||||||
code_feedback = data['code_feedback']
|
code_feedback = data['code_feedback']
|
||||||
@ -357,6 +358,9 @@ class PRReviewer:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def set_review_labels(self, data):
|
def set_review_labels(self, data):
|
||||||
|
if not get_settings().config.publish_output:
|
||||||
|
return
|
||||||
|
|
||||||
if (get_settings().pr_reviewer.enable_review_labels_security or
|
if (get_settings().pr_reviewer.enable_review_labels_security or
|
||||||
get_settings().pr_reviewer.enable_review_labels_effort):
|
get_settings().pr_reviewer.enable_review_labels_effort):
|
||||||
try:
|
try:
|
||||||
|
@ -15,5 +15,5 @@ class TestClipTokens:
|
|||||||
|
|
||||||
max_tokens = 10
|
max_tokens = 10
|
||||||
result = clip_tokens(text, max_tokens)
|
result = clip_tokens(text, max_tokens)
|
||||||
expected_results = 'line1\nline2\nline3\nli...(truncated)'
|
expected_results = 'line1\nline2\nline3\nli\n...(truncated)'
|
||||||
assert result == expected_results
|
assert result == expected_results
|
||||||
|
50
tests/unittest/test_github_action_output.py
Normal file
50
tests/unittest/test_github_action_output.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
from pr_agent.algo.utils import get_settings, github_action_output
|
||||||
|
|
||||||
|
class TestGitHubOutput:
|
||||||
|
def test_github_action_output_enabled(self, monkeypatch, tmp_path):
|
||||||
|
get_settings().set('GITHUB_ACTION_CONFIG.ENABLE_OUTPUT', True)
|
||||||
|
monkeypatch.setenv('GITHUB_OUTPUT', str(tmp_path / 'output'))
|
||||||
|
output_data = {'key1': {'value1': 1, 'value2': 2}}
|
||||||
|
key_name = 'key1'
|
||||||
|
|
||||||
|
github_action_output(output_data, key_name)
|
||||||
|
|
||||||
|
with open(str(tmp_path / 'output'), 'r') as f:
|
||||||
|
env_value = f.read()
|
||||||
|
|
||||||
|
actual_key = env_value.split('=')[0]
|
||||||
|
actual_data = json.loads(env_value.split('=')[1])
|
||||||
|
|
||||||
|
assert actual_key == key_name
|
||||||
|
assert actual_data == output_data[key_name]
|
||||||
|
|
||||||
|
def test_github_action_output_disabled(self, monkeypatch, tmp_path):
|
||||||
|
get_settings().set('GITHUB_ACTION_CONFIG.ENABLE_OUTPUT', False)
|
||||||
|
monkeypatch.setenv('GITHUB_OUTPUT', str(tmp_path / 'output'))
|
||||||
|
output_data = {'key1': {'value1': 1, 'value2': 2}}
|
||||||
|
key_name = 'key1'
|
||||||
|
|
||||||
|
github_action_output(output_data, key_name)
|
||||||
|
|
||||||
|
assert not os.path.exists(str(tmp_path / 'output'))
|
||||||
|
|
||||||
|
def test_github_action_output_notset(self, monkeypatch, tmp_path):
|
||||||
|
# not set config
|
||||||
|
monkeypatch.setenv('GITHUB_OUTPUT', str(tmp_path / 'output'))
|
||||||
|
output_data = {'key1': {'value1': 1, 'value2': 2}}
|
||||||
|
key_name = 'key1'
|
||||||
|
|
||||||
|
github_action_output(output_data, key_name)
|
||||||
|
|
||||||
|
assert not os.path.exists(str(tmp_path / 'output'))
|
||||||
|
|
||||||
|
def test_github_action_output_error_case(self, monkeypatch, tmp_path):
|
||||||
|
monkeypatch.setenv('GITHUB_OUTPUT', str(tmp_path / 'output'))
|
||||||
|
output_data = None # invalid data
|
||||||
|
key_name = 'key1'
|
||||||
|
|
||||||
|
github_action_output(output_data, key_name)
|
||||||
|
|
||||||
|
assert not os.path.exists(str(tmp_path / 'output'))
|
Reference in New Issue
Block a user