From a3d572fb69df975ef33c53c61527efe86ff6a5a0 Mon Sep 17 00:00:00 2001 From: Yu Ishikawa Date: Wed, 30 Oct 2024 09:55:15 +0900 Subject: [PATCH 1/4] Add `.pre-commit-config.yaml` Signed-off-by: Yu Ishikawa --- .pre-commit-config.yaml | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..ff495d30e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,46 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks + +default_language_version: + python: python3 + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: check-added-large-files + - id: check-toml + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/rhysd/actionlint + rev: v1.7.3 + hooks: + - id: actionlint + - repo: https://github.com/pycqa/isort + # rev must match what's in dev-requirements.txt + rev: 5.13.2 + hooks: + - id: isort + # - repo: https://github.com/PyCQA/bandit + # rev: 1.7.10 + # hooks: + # - id: bandit + # args: [ + # "-c", "pyproject.toml", + # ] + # - repo: https://github.com/astral-sh/ruff-pre-commit + # rev: v0.7.1 + # hooks: + # - id: ruff + # args: + # - --fix + # - id: ruff-format + # - repo: https://github.com/PyCQA/autoflake + # rev: v2.3.1 + # hooks: + # - id: autoflake + # args: + # - --in-place + # - --remove-all-unused-imports + # - --remove-unused-variables From 81dea65856a9546bd63efc2e31a9529b8e63f43d Mon Sep 17 00:00:00 2001 From: Yu Ishikawa Date: Wed, 30 Oct 2024 09:56:03 +0900 Subject: [PATCH 2/4] Format files by `pre-commit run -a` Signed-off-by: Yu Ishikawa --- .github/workflows/build-and-test.yaml | 2 - .github/workflows/code_coverage.yaml | 4 +- .github/workflows/docs-ci.yaml | 6 +- .github/workflows/e2e_tests.yaml | 2 +- .github/workflows/pr-agent-review.yaml | 5 +- .gitignore | 2 +- .pre-commit-config.yaml | 8 +-- LICENSE | 2 +- MANIFEST.in | 2 +- README.md | 6 +- RELEASE_NOTES.md | 2 +- docs/docs/assets/logo.svg | 2 +- docs/docs/chrome-extension/data_privacy.md | 1 - docs/docs/chrome-extension/index.md | 2 +- .../docs/core-abilities/code_oriented_yaml.md | 2 +- .../core-abilities/compression_strategy.md | 4 +- docs/docs/core-abilities/dynamic_context.md | 20 +++--- docs/docs/core-abilities/impact_evaluation.md | 2 +- docs/docs/core-abilities/index.md | 4 +- docs/docs/core-abilities/interactivity.md | 2 +- docs/docs/core-abilities/metadata.md | 2 +- docs/docs/core-abilities/self_reflection.md | 8 +-- docs/docs/faq/index.md | 10 +-- docs/docs/finetuning_benchmark/index.md | 10 +-- docs/docs/installation/azure.md | 10 +-- docs/docs/installation/github.md | 12 ++-- docs/docs/installation/gitlab.md | 2 +- docs/docs/installation/index.md | 4 +- docs/docs/installation/locally.md | 6 +- docs/docs/installation/pr_agent_pro.md | 6 +- docs/docs/overview/index.md | 2 +- docs/docs/overview/pr_agent_pro.md | 4 +- docs/docs/tools/analyze.md | 2 +- docs/docs/tools/ask.md | 4 +- docs/docs/tools/custom_labels.md | 2 +- docs/docs/tools/custom_prompt.md | 4 +- docs/docs/tools/documentation.md | 2 +- docs/docs/tools/improve.md | 26 ++++---- docs/docs/tools/improve_component.md | 2 +- docs/docs/tools/index.md | 2 +- docs/docs/tools/review.md | 25 ++++---- docs/docs/tools/similar_code.md | 2 +- docs/docs/tools/similar_issues.md | 4 +- docs/docs/tools/test.md | 2 +- docs/docs/tools/update_changelog.md | 2 +- .../docs/usage-guide/EXAMPLE_BEST_PRACTICE.md | 2 +- .../docs/usage-guide/automations_and_usage.md | 20 +++--- docs/docs/usage-guide/changing_a_model.md | 8 +-- .../docs/usage-guide/configuration_options.md | 2 +- docs/docs/usage-guide/index.md | 4 +- docs/docs/usage-guide/introduction.md | 1 - docs/docs/usage-guide/mail_notifications.md | 4 +- docs/mkdocs.yml | 4 +- docs/overrides/main.html | 4 +- docs/overrides/partials/footer.html | 2 +- .../integrations/analytics/custom.html | 2 +- pr_agent/__init__.py | 1 - pr_agent/agent/pr_agent.py | 1 - pr_agent/algo/ai_handlers/base_ai_handler.py | 4 +- .../algo/ai_handlers/langchain_ai_handler.py | 14 ++--- .../algo/ai_handlers/litellm_ai_handler.py | 3 +- .../algo/ai_handlers/openai_ai_handler.py | 2 +- pr_agent/algo/git_patch_processing.py | 4 +- pr_agent/algo/language_handler.py | 2 - pr_agent/algo/pr_processing.py | 9 +-- pr_agent/algo/token_handler.py | 7 ++- pr_agent/algo/utils.py | 4 +- pr_agent/cli.py | 2 +- pr_agent/git_providers/__init__.py | 10 +-- .../git_providers/azuredevops_provider.py | 25 ++++---- pr_agent/git_providers/bitbucket_provider.py | 5 +- .../bitbucket_server_provider.py | 9 +-- pr_agent/git_providers/codecommit_provider.py | 22 ++++--- pr_agent/git_providers/gerrit_provider.py | 2 +- pr_agent/git_providers/git_provider.py | 6 +- pr_agent/git_providers/github_provider.py | 10 ++- pr_agent/git_providers/gitlab_provider.py | 9 ++- pr_agent/git_providers/local_git_provider.py | 2 +- pr_agent/git_providers/utils.py | 5 +- pr_agent/identity_providers/__init__.py | 5 +- .../default_identity_provider.py | 3 +- pr_agent/secret_providers/__init__.py | 6 +- .../servers/azuredevops_server_webhook.py | 7 +-- pr_agent/servers/bitbucket_server_webhook.py | 4 +- pr_agent/servers/github_app.py | 3 +- pr_agent/servers/github_polling.py | 7 ++- pr_agent/servers/gitlab_webhook.py | 2 +- pr_agent/servers/help.py | 14 ++--- pr_agent/servers/serverless.py | 1 - pr_agent/servers/utils.py | 2 +- pr_agent/settings/.secrets_template.toml | 2 +- pr_agent/settings/custom_labels.toml | 2 +- pr_agent/settings/language_extensions.toml | 2 +- .../settings/pr_code_suggestions_prompts.toml | 2 +- pr_agent/tools/pr_code_suggestions.py | 21 ++++--- pr_agent/tools/pr_description.py | 25 +++++--- pr_agent/tools/pr_generate_labels.py | 6 +- pr_agent/tools/pr_help_message.py | 6 +- pr_agent/tools/pr_line_questions.py | 4 +- pr_agent/tools/pr_reviewer.py | 20 ++++-- pr_agent/tools/pr_similar_issue.py | 24 +++---- pr_agent/tools/pr_update_changelog.py | 4 +- pyproject.toml | 62 ++++++++++--------- tests/e2e_tests/e2e_utils.py | 1 - tests/e2e_tests/test_bitbucket_app.py | 12 ++-- tests/e2e_tests/test_github_app.py | 8 ++- tests/e2e_tests/test_gitlab_webhook.py | 8 ++- tests/unittest/test_azure_devops_parsing.py | 2 +- tests/unittest/test_bitbucket_provider.py | 12 ++-- tests/unittest/test_codecommit_client.py | 1 + tests/unittest/test_codecommit_provider.py | 10 +-- tests/unittest/test_convert_to_markdown.py | 10 +-- tests/unittest/test_delete_hunks.py | 8 +-- tests/unittest/test_extend_patch.py | 1 + tests/unittest/test_file_filter.py | 2 + ...nd_line_number_of_relevant_line_in_file.py | 5 +- tests/unittest/test_github_action_output.py | 30 ++++----- tests/unittest/test_handle_patch_deletions.py | 2 +- tests/unittest/test_language_handler.py | 4 +- tests/unittest/test_load_yaml.py | 4 -- tests/unittest/test_parse_code_suggestion.py | 4 +- tests/unittest/test_try_fix_yaml.py | 8 +-- 122 files changed, 422 insertions(+), 390 deletions(-) diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml index bfe87dbdd..9f56c3e51 100644 --- a/.github/workflows/build-and-test.yaml +++ b/.github/workflows/build-and-test.yaml @@ -37,5 +37,3 @@ jobs: name: Test dev docker run: | docker run --rm codiumai/pr-agent:test pytest -v tests/unittest - - diff --git a/.github/workflows/code_coverage.yaml b/.github/workflows/code_coverage.yaml index 136ed9a7c..de3720246 100644 --- a/.github/workflows/code_coverage.yaml +++ b/.github/workflows/code_coverage.yaml @@ -37,7 +37,7 @@ jobs: - id: code_cov name: Test dev docker run: | - docker run --name test_container codiumai/pr-agent:test pytest tests/unittest --cov=pr_agent --cov-report term --cov-report xml:coverage.xml + docker run --name test_container codiumai/pr-agent:test pytest tests/unittest --cov=pr_agent --cov-report term --cov-report xml:coverage.xml docker cp test_container:/app/coverage.xml coverage.xml docker rm test_container @@ -51,4 +51,4 @@ jobs: - name: Upload coverage to Codecov uses: codecov/codecov-action@v4.0.1 with: - token: ${{ secrets.CODECOV_TOKEN }} \ No newline at end of file + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/docs-ci.yaml b/.github/workflows/docs-ci.yaml index b260039ec..3e59de111 100644 --- a/.github/workflows/docs-ci.yaml +++ b/.github/workflows/docs-ci.yaml @@ -1,4 +1,4 @@ -name: docs-ci +name: docs-ci on: push: branches: @@ -20,14 +20,14 @@ jobs: - uses: actions/setup-python@v5 with: python-version: 3.x - - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV + - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV - uses: actions/cache@v4 with: key: mkdocs-material-${{ env.cache_id }} path: .cache restore-keys: | mkdocs-material- - - run: pip install mkdocs-material + - run: pip install mkdocs-material - run: pip install "mkdocs-material[imaging]" - run: pip install mkdocs-glightbox - run: mkdocs gh-deploy -f docs/mkdocs.yml --force diff --git a/.github/workflows/e2e_tests.yaml b/.github/workflows/e2e_tests.yaml index e49bcea39..07602d7f4 100644 --- a/.github/workflows/e2e_tests.yaml +++ b/.github/workflows/e2e_tests.yaml @@ -43,4 +43,4 @@ jobs: - id: test3 name: E2E bitbucket app run: | - docker run -e BITBUCKET.USERNAME=${{ secrets.BITBUCKET_USERNAME }} -e BITBUCKET.PASSWORD=${{ secrets.BITBUCKET_PASSWORD }} --rm codiumai/pr-agent:test pytest -v tests/e2e_tests/test_bitbucket_app.py \ No newline at end of file + docker run -e BITBUCKET.USERNAME=${{ secrets.BITBUCKET_USERNAME }} -e BITBUCKET.PASSWORD=${{ secrets.BITBUCKET_PASSWORD }} --rm codiumai/pr-agent:test pytest -v tests/e2e_tests/test_bitbucket_app.py diff --git a/.github/workflows/pr-agent-review.yaml b/.github/workflows/pr-agent-review.yaml index aa7a8fe01..4d2a04acb 100644 --- a/.github/workflows/pr-agent-review.yaml +++ b/.github/workflows/pr-agent-review.yaml @@ -1,4 +1,4 @@ -# This workflow enables developers to call PR-Agents `/[actions]` in PR's comments and upon PR creation. +# This workflow enables developers to call PR-Agents `/[actions]` in PR's comments and upon PR creation. # Learn more at https://www.codium.ai/pr-agent/ # This is v0.2 of this workflow file @@ -30,6 +30,3 @@ jobs: GITHUB_ACTION_CONFIG.AUTO_DESCRIBE: true GITHUB_ACTION_CONFIG.AUTO_REVIEW: true GITHUB_ACTION_CONFIG.AUTO_IMPROVE: true - - - diff --git a/.gitignore b/.gitignore index 9fcb91939..ec1de25f4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,4 @@ dist/ *.egg-info/ build/ .DS_Store -docs/.cache/ \ No newline at end of file +docs/.cache/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ff495d30e..e5971b70d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,10 +13,10 @@ repos: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - - repo: https://github.com/rhysd/actionlint - rev: v1.7.3 - hooks: - - id: actionlint + # - repo: https://github.com/rhysd/actionlint + # rev: v1.7.3 + # hooks: + # - id: actionlint - repo: https://github.com/pycqa/isort # rev must match what's in dev-requirements.txt rev: 5.13.2 diff --git a/LICENSE b/LICENSE index 633ab1c95..a5fcacc9a 100644 --- a/LICENSE +++ b/LICENSE @@ -199,4 +199,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file + limitations under the License. diff --git a/MANIFEST.in b/MANIFEST.in index ccb173366..194b3def9 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,2 @@ recursive-include pr_agent *.toml -recursive-exclude pr_agent *.secrets.toml \ No newline at end of file +recursive-exclude pr_agent *.secrets.toml diff --git a/README.md b/README.md index ef5354349..e1ef104cd 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Qode Merge PR-Agent aims to help efficiently review and handle pull requests, by - [PR-Agent Pro ๐Ÿ’Ž](https://pr-agent-docs.codium.ai/overview/pr_agent_pro/) - [How it works](#how-it-works) - [Why use PR-Agent?](#why-use-pr-agent) - + ## News and Updates ### October 27, 2024 @@ -55,7 +55,7 @@ Read more about this novel feature [here](https://qodo-merge-docs.qodo.ai/tools/ ### October 21, 2024 -**Disable publishing labels by default:** +**Disable publishing labels by default:** The default setting for `pr_description.publish_labels` has been updated to `false`. This means that labels generated by the `/describe` tool will no longer be published, unless this configuration is explicitly set to `true`. @@ -258,7 +258,7 @@ Note that when you set your own PR-Agent or use CodiumAI hosted PR-Agent, there 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. 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. See [here](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/) for a list of features available in PR-Agent Pro. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 3dab48f92..7ce674d2e 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -88,7 +88,7 @@ Significant documentation updates (see [Installation Guide](https://github.com/C - codiumai/pr-agent:0.7-gitlab_webhook - codiumai/pr-agent:0.7-github_polling - codiumai/pr-agent:0.7-github_action - + ### Added::Algo - New tool /similar_issue - Currently on GitHub app and CLI: indexes the issues in the repo, find the most similar issues to the target issue. - Describe markers: Empower the /describe tool with a templating capability (see more details in https://github.com/Codium-ai/pr-agent/pull/273). diff --git a/docs/docs/assets/logo.svg b/docs/docs/assets/logo.svg index 0b4ddbbab..a22defe7f 100644 --- a/docs/docs/assets/logo.svg +++ b/docs/docs/assets/logo.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/docs/docs/chrome-extension/data_privacy.md b/docs/docs/chrome-extension/data_privacy.md index 14753a0c6..848f8f2df 100644 --- a/docs/docs/chrome-extension/data_privacy.md +++ b/docs/docs/chrome-extension/data_privacy.md @@ -2,4 +2,3 @@ We take your code's security and privacy seriously: - The Chrome extension will not send your code to any external servers. - For private repositories, we will first validate the user's identity and permissions. After authentication, we generate responses using the existing Qodo Merge Pro integration. - diff --git a/docs/docs/chrome-extension/index.md b/docs/docs/chrome-extension/index.md index 6885df4b5..f722639c5 100644 --- a/docs/docs/chrome-extension/index.md +++ b/docs/docs/chrome-extension/index.md @@ -2,7 +2,7 @@ With a single-click installation you will gain access to a context-aware chat on your pull requests code, a toolbar extension with multiple AI feedbacks, Qodo Merge filters, and additional abilities. -The extension is powered by top code models like Claude 3.5 Sonnet and GPT4. All the extension's features are free to use on public repositories. +The extension is powered by top code models like Claude 3.5 Sonnet and GPT4. All the extension's features are free to use on public repositories. For private repositories, you will need to install [Qodo Merge Pro](https://github.com/apps/codiumai-pr-agent-pro) in addition to the extension (Quick GitHub app setup with a 14-day free trial. No credit card needed). For a demonstration of how to install Qodo Merge Pro and use it with the Chrome extension, please refer to the tutorial video at the provided [link](https://codium.ai/images/pr_agent/private_repos.mp4). diff --git a/docs/docs/core-abilities/code_oriented_yaml.md b/docs/docs/core-abilities/code_oriented_yaml.md index 32cfee7ff..e65f83664 100644 --- a/docs/docs/core-abilities/code_oriented_yaml.md +++ b/docs/docs/core-abilities/code_oriented_yaml.md @@ -1,2 +1,2 @@ ## Overview -TBD \ No newline at end of file +TBD diff --git a/docs/docs/core-abilities/compression_strategy.md b/docs/docs/core-abilities/compression_strategy.md index c09de0dbf..1115c33c8 100644 --- a/docs/docs/core-abilities/compression_strategy.md +++ b/docs/docs/core-abilities/compression_strategy.md @@ -12,9 +12,9 @@ We prioritize the languages of the repo based on the following criteria: 1. Exclude binary files and non code files (e.g. images, pdfs, etc) 2. Given the main languages used in the repo -3. We sort the PR files by the most common languages in the repo (in descending order): +3. We sort the PR files by the most common languages in the repo (in descending order): * ```[[file.py, file2.py],[file3.js, file4.jsx],[readme.md]]``` - + ### Small PR In this case, we can fit the entire PR in a single prompt: diff --git a/docs/docs/core-abilities/dynamic_context.md b/docs/docs/core-abilities/dynamic_context.md index b8b71a30d..eff3e60c9 100644 --- a/docs/docs/core-abilities/dynamic_context.md +++ b/docs/docs/core-abilities/dynamic_context.md @@ -1,7 +1,7 @@ ## TL;DR -Qodo Merge uses an **asymmetric and dynamic context strategy** to improve AI analysis of code changes in pull requests. -It provides more context before changes than after, and dynamically adjusts the context based on code structure (e.g., enclosing functions or classes). +Qodo Merge uses an **asymmetric and dynamic context strategy** to improve AI analysis of code changes in pull requests. +It provides more context before changes than after, and dynamically adjusts the context based on code structure (e.g., enclosing functions or classes). This approach balances providing sufficient context for accurate analysis, while avoiding needle-in-the-haystack information overload that could degrade AI performance or exceed token limits. ## Introduction @@ -17,12 +17,12 @@ Pull request code changes are retrieved in a unified diff format, showing three code line that already existed in the file... code line that already existed in the file... code line that already existed in the file... - + @@ -26,2 +26,4 @@ def func2(): ... ``` -This unified diff format can be challenging for AI models to interpret accurately, as it provides limited context for understanding the full scope of code changes. +This unified diff format can be challenging for AI models to interpret accurately, as it provides limited context for understanding the full scope of code changes. The presentation of code using '+', '-', and ' ' symbols to indicate additions, deletions, and unchanged lines respectively also differs from the standard code formatting typically used to train AI models. @@ -37,7 +37,7 @@ Pros: Cons: - Excessive context may overwhelm the model with extraneous information, creating a "needle in a haystack" scenario where focusing on the relevant details (the code that actually changed) becomes challenging. -LLM quality is known to degrade when the context gets larger. +LLM quality is known to degrade when the context gets larger. Pull requests often encompass multiple changes across many files, potentially spanning hundreds of lines of modified code. This complexity presents a genuine risk of overwhelming the model with excessive context. - Increased context expands the token count, increasing processing time and cost, and may prevent the model from processing the entire pull request in a single pass. @@ -47,18 +47,18 @@ To address these challenges, Qodo Merge employs an **asymmetric** and **dynamic* **Asymmetric:** -We start by recognizing that the context preceding a code change is typically more crucial for understanding the modification than the context following it. +We start by recognizing that the context preceding a code change is typically more crucial for understanding the modification than the context following it. Consequently, Qodo Merge implements an asymmetric context policy, decoupling the context window into two distinct segments: one for the code before the change and another for the code after. -By independently adjusting each context window, Qodo Merge can supply the model with a more tailored and pertinent context for individual code changes. +By independently adjusting each context window, Qodo Merge can supply the model with a more tailored and pertinent context for individual code changes. **Dynamic:** We also employ a "dynamic" context strategy. -We start by recognizing that the optimal context for a code change often corresponds to its enclosing code component (e.g., function, class), rather than a fixed number of lines. +We start by recognizing that the optimal context for a code change often corresponds to its enclosing code component (e.g., function, class), rather than a fixed number of lines. Consequently, we dynamically adjust the context window based on the code's structure, ensuring the model receives the most pertinent information for each modification. -To prevent overwhelming the model with excessive context, we impose a limit on the number of lines searched when identifying the enclosing component. +To prevent overwhelming the model with excessive context, we impose a limit on the number of lines searched when identifying the enclosing component. This balance allows for comprehensive understanding while maintaining efficiency and limiting context token usage. ## Appendix - relevant configuration options @@ -69,4 +69,4 @@ allow_dynamic_context=true # Allow dynamic context extension max_extra_lines_before_dynamic_context = 8 # will try to include up to X extra lines before the hunk in the patch, until we reach an enclosing function or class patch_extra_lines_before = 3 # Number of extra lines (+3 default ones) to include before each hunk in the patch patch_extra_lines_after = 1 # Number of extra lines (+3 default ones) to include after each hunk in the patch -``` \ No newline at end of file +``` diff --git a/docs/docs/core-abilities/impact_evaluation.md b/docs/docs/core-abilities/impact_evaluation.md index 41db3b527..2790411e6 100644 --- a/docs/docs/core-abilities/impact_evaluation.md +++ b/docs/docs/core-abilities/impact_evaluation.md @@ -41,4 +41,4 @@ Here are key metrics that the dashboard tracks: #### Suggestion Score Distribution ![Impacted_Suggestion_Score](https://codium.ai/images/pr_agent/impacted_score_dist.png){width=512} -> Explanation: The distribution of the suggestion score for the implemented suggestions, ensuring that higher-scored suggestions truly represent more significant improvements. +> Explanation: The distribution of the suggestion score for the implemented suggestions, ensuring that higher-scored suggestions truly represent more significant improvements. diff --git a/docs/docs/core-abilities/index.md b/docs/docs/core-abilities/index.md index c9f288bc4..2d025c9dd 100644 --- a/docs/docs/core-abilities/index.md +++ b/docs/docs/core-abilities/index.md @@ -13,7 +13,7 @@ Qodo Merge utilizes a variety of core abilities to provide a comprehensive and e ## Blogs -Here are some additional technical blogs from Qodo, that delve deeper into the core capabilities and features of Large Language Models (LLMs) when applied to coding tasks. +Here are some additional technical blogs from Qodo, that delve deeper into the core capabilities and features of Large Language Models (LLMs) when applied to coding tasks. These resources provide more comprehensive insights into leveraging LLMs for software development. ### Code Generation and LLMs @@ -25,4 +25,4 @@ These resources provide more comprehensive insights into leveraging LLMs for sof - [Introduction to Code Coverage Testing](https://www.qodo.ai/blog/introduction-to-code-coverage-testing/) ### Cost Optimization -- [Reduce Your Costs by 30% When Using GPT for Python Code](https://www.qodo.ai/blog/reduce-your-costs-by-30-when-using-gpt-3-for-python-code/) \ No newline at end of file +- [Reduce Your Costs by 30% When Using GPT for Python Code](https://www.qodo.ai/blog/reduce-your-costs-by-30-when-using-gpt-3-for-python-code/) diff --git a/docs/docs/core-abilities/interactivity.md b/docs/docs/core-abilities/interactivity.md index e484d641d..e107f781d 100644 --- a/docs/docs/core-abilities/interactivity.md +++ b/docs/docs/core-abilities/interactivity.md @@ -1,2 +1,2 @@ ## Interactive invocation ๐Ÿ’Ž -TBD \ No newline at end of file +TBD diff --git a/docs/docs/core-abilities/metadata.md b/docs/docs/core-abilities/metadata.md index 570da42ea..2b90b0153 100644 --- a/docs/docs/core-abilities/metadata.md +++ b/docs/docs/core-abilities/metadata.md @@ -53,4 +53,4 @@ __old hunk__ (4) All the metadata described above represents several level of cumulative analysis - ranging from hunk level, to file level, to PR level, to organization level. -This comprehensive approach enables Qodo Merge AI models to generate more precise and contextually relevant suggestions and feedback. \ No newline at end of file +This comprehensive approach enables Qodo Merge AI models to generate more precise and contextually relevant suggestions and feedback. diff --git a/docs/docs/core-abilities/self_reflection.md b/docs/docs/core-abilities/self_reflection.md index b8acc3951..894cee69a 100644 --- a/docs/docs/core-abilities/self_reflection.md +++ b/docs/docs/core-abilities/self_reflection.md @@ -1,7 +1,7 @@ ## TL;DR -Qodo Merge implements a **self-reflection** process where the AI model reflects, scores, and re-ranks its own suggestions, eliminating irrelevant or incorrect ones. -This approach improves the quality and relevance of suggestions, saving users time and enhancing their experience. +Qodo Merge implements a **self-reflection** process where the AI model reflects, scores, and re-ranks its own suggestions, eliminating irrelevant or incorrect ones. +This approach improves the quality and relevance of suggestions, saving users time and enhancing their experience. Configuration options allow users to set a score threshold for further filtering out suggestions. ## Introduction - Efficient Review with Hierarchical Presentation @@ -24,7 +24,7 @@ The AI model is initially tasked with generating suggestions, and outputting the However, in practice we observe that models often struggle to simultaneously generate high-quality code suggestions and rank them well in a single pass. Furthermore, the initial set of generated suggestions sometimes contains easily identifiable errors. -To address these issues, we implemented a "self-reflection" process that refines suggestion ranking and eliminates irrelevant or incorrect proposals. +To address these issues, we implemented a "self-reflection" process that refines suggestion ranking and eliminates irrelevant or incorrect proposals. This process consists of the following steps: 1. Presenting the generated suggestions to the model in a follow-up call. @@ -48,4 +48,4 @@ This results in a more refined and valuable set of suggestions for the user, sav [pr_code_suggestions] self_reflect_on_suggestions = true # Enable self-reflection on code suggestions suggestions_score_threshold = 0 # Filter out suggestions with a score below this threshold (0-10) -``` \ No newline at end of file +``` diff --git a/docs/docs/faq/index.md b/docs/docs/faq/index.md index e01920b8e..dcd5df6b1 100644 --- a/docs/docs/faq/index.md +++ b/docs/docs/faq/index.md @@ -31,11 +31,11 @@ ___ - The hierarchical structure of the suggestions is designed to help the user to _quickly_ understand them, and to decide which ones are relevant and which are not: - + - Only if the `Category` header is relevant, the user should move to the summarized suggestion description. - Only if the summarized suggestion description is relevant, the user should click on the collapsible, to read the full suggestion description with a code preview example. - - In addition, we recommend to use the [`extra_instructions`](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices) field to guide the model to suggestions that are more relevant to the specific needs of the project. + - In addition, we recommend to use the [`extra_instructions`](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices) field to guide the model to suggestions that are more relevant to the specific needs of the project. - The interactive [PR chat](https://qodo-merge-docs.qodo.ai/chrome-extension/) also provides an easy way to get more tailored suggestions and feedback from the AI model. ___ @@ -51,7 +51,7 @@ ___ #### Answer:4 No. Qodo Merge strict privacy policy ensures that your code is not stored or used for training purposes. - + For a detailed overview of our data privacy policy, please refer to [this link](https://qodo-merge-docs.qodo.ai/overview/data_privacy/) ___ @@ -59,9 +59,9 @@ ___ ??? note "Question: Can I use my own LLM keys with Qodo Merge?" #### Answer:5 - When you self-host, you use your own keys. + When you self-host, you use your own keys. Qodo Merge Pro with SaaS deployment is a hosted version of Qodo Merge, where Qodo manages the infrastructure and the keys. For enterprise customers, on-prem deployment is also available. [Contact us](https://www.codium.ai/contact/#pricing) for more information. -___ \ No newline at end of file +___ diff --git a/docs/docs/finetuning_benchmark/index.md b/docs/docs/finetuning_benchmark/index.md index 5a002df8d..b479ff0a6 100644 --- a/docs/docs/finetuning_benchmark/index.md +++ b/docs/docs/finetuning_benchmark/index.md @@ -84,10 +84,10 @@ command: improve model1_score: 9, model2_score: 6, why: | - Response 1 is better because it provides more actionable and specific suggestions that directly - enhance the code's maintainability, performance, and best practices. For example, it suggests - using a variable for reusable widget instances and using named routes for navigation, which - are practical improvements. In contrast, Response 2 focuses more on general advice and less - actionable suggestions, such as changing variable names and adding comments, which are less + Response 1 is better because it provides more actionable and specific suggestions that directly + enhance the code's maintainability, performance, and best practices. For example, it suggests + using a variable for reusable widget instances and using named routes for navigation, which + are practical improvements. In contrast, Response 2 focuses more on general advice and less + actionable suggestions, such as changing variable names and adding comments, which are less critical for immediate code improvement." ``` diff --git a/docs/docs/installation/azure.md b/docs/docs/installation/azure.md index 62ea49ba0..22db96a2d 100644 --- a/docs/docs/installation/azure.md +++ b/docs/docs/installation/azure.md @@ -40,7 +40,7 @@ stages: export azure_devops__org="$ORG_URL" export config__git_provider="azure" - + pr-agent --pr_url="$PR_URL" describe pr-agent --pr_url="$PR_URL" review pr-agent --pr_url="$PR_URL" improve @@ -65,11 +65,11 @@ git_provider="azure" ``` Azure DevOps provider supports [PAT token](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows) or [DefaultAzureCredential](https://learn.microsoft.com/en-us/azure/developer/python/sdk/authentication-overview#authentication-in-server-environments) authentication. -PAT is faster to create, but has build in expiration date, and will use the user identity for API calls. +PAT is faster to create, but has build in expiration date, and will use the user identity for API calls. Using DefaultAzureCredential you can use managed identity or Service principle, which are more secure and will create separate ADO user identity (via AAD) to the agent. -If PAT was chosen, you can assign the value in .secrets.toml. -If DefaultAzureCredential was chosen, you can assigned the additional env vars like AZURE_CLIENT_SECRET directly, +If PAT was chosen, you can assign the value in .secrets.toml. +If DefaultAzureCredential was chosen, you can assigned the additional env vars like AZURE_CLIENT_SECRET directly, or use managed identity/az cli (for local development) without any additional configuration. in any case, 'org' value must be assigned in .secrets.toml: ``` @@ -80,7 +80,7 @@ org = "https://dev.azure.com/YOUR_ORGANIZATION/" ### Azure DevOps Webhook -To trigger from an Azure webhook, you need to manually [add a webhook](https://learn.microsoft.com/en-us/azure/devops/service-hooks/services/webhooks?view=azure-devops). +To trigger from an Azure webhook, you need to manually [add a webhook](https://learn.microsoft.com/en-us/azure/devops/service-hooks/services/webhooks?view=azure-devops). Use the "Pull request created" type to trigger a review, or "Pull request commented on" to trigger any supported comment with / comment on the relevant PR. Note that for the "Pull request commented on" trigger, only API v2.0 is supported. diff --git a/docs/docs/installation/github.md b/docs/docs/installation/github.md index 8035d6db3..b7e326ecf 100644 --- a/docs/docs/installation/github.md +++ b/docs/docs/installation/github.md @@ -60,7 +60,7 @@ See detailed usage instructions in the [USAGE GUIDE](https://qodo-merge-docs.qod uses: docker://codiumai/pr-agent:0.23-github_action ... ``` - + For enhanced security, you can also specify the Docker image by its [digest](https://hub.docker.com/repository/docker/codiumai/pr-agent/tags): ```yaml ... @@ -71,17 +71,17 @@ See detailed usage instructions in the [USAGE GUIDE](https://qodo-merge-docs.qod ... ``` -### Action for GitHub enterprise server +### Action for GitHub enterprise server !!! tip "" To use the action with a GitHub enterprise server, add an environment variable `GITHUB.BASE_URL` with the API URL of your GitHub server. - + For example, if your GitHub server is at `https://github.mycompany.com`, add the following to your workflow file: ```yaml env: # ... previous environment values GITHUB.BASE_URL: "https://github.mycompany.com/api/v3" ``` - + --- @@ -118,7 +118,7 @@ git clone https://github.com/Codium-ai/pr-agent.git ``` 5) Copy the secrets template file and fill in the following: - + ``` cp pr_agent/settings/.secrets_template.toml pr_agent/settings/.secrets.toml # Edit .secrets.toml file @@ -147,7 +147,7 @@ cp pr_agent/settings/.secrets_template.toml pr_agent/settings/.secrets.toml - mountPath: /app/pr_agent/settings_prod name: settings-volume ``` - + > Another option is to set the secrets as environment variables in your deployment environment, for example `OPENAI.KEY` and `GITHUB.USER_TOKEN`. 6) Build a Docker image for the app and optionally push it to a Docker repository. We'll use Dockerhub as an example: diff --git a/docs/docs/installation/gitlab.md b/docs/docs/installation/gitlab.md index 5a1f23d4c..513cdcb95 100644 --- a/docs/docs/installation/gitlab.md +++ b/docs/docs/installation/gitlab.md @@ -74,4 +74,4 @@ docker push codiumai/pr-agent:gitlab_webhook # Push to your Docker repository 6. Create a webhook in GitLab. Set the URL to ```http[s]:///webhook```, the secret token to the generated secret from step 2, and enable the triggers `push`, `comments` and `merge request events`. 7. Test your installation by opening a merge request or commenting on a merge request using one of CodiumAI's commands. -boxes \ No newline at end of file +boxes diff --git a/docs/docs/installation/index.md b/docs/docs/installation/index.md index 27c9a3b2a..c5be61899 100644 --- a/docs/docs/installation/index.md +++ b/docs/docs/installation/index.md @@ -15,7 +15,7 @@ There are several ways to use self-hosted Qodo Merge: - [Azure DevOps](./azure.md) ## Qodo Merge Pro ๐Ÿ’Ž -Qodo Merge Pro, an app hosted by CodiumAI for GitHub\GitLab\BitBucket, is also available. +Qodo Merge Pro, an app hosted by CodiumAI for GitHub\GitLab\BitBucket, is also available.
-With Qodo Merge Pro, installation is as simple as signing up and adding the Qodo Merge app to your relevant repo. +With Qodo Merge Pro, installation is as simple as signing up and adding the Qodo Merge app to your relevant repo. See [here](https://qodo-merge-docs.qodo.ai/installation/pr_agent_pro/) for more details. diff --git a/docs/docs/installation/locally.md b/docs/docs/installation/locally.md index fad9d7892..2d9859bf2 100644 --- a/docs/docs/installation/locally.md +++ b/docs/docs/installation/locally.md @@ -45,7 +45,7 @@ To invoke a tool (for example `review`), you can run directly from the Docker im ``` docker run --rm -it -e OPENAI.KEY= -e GITHUB.USER_TOKEN= codiumai/pr-agent:latest --pr_url review ``` - If you are using GitHub enterprise server, you need to specify the custom url as variable. + If you are using GitHub enterprise server, you need to specify the custom url as variable. For example, if your GitHub server is at `https://github.mycompany.com`, add the following to the command: ``` -e GITHUB.BASE_URL=https://github.mycompany.com/api/v3 @@ -58,7 +58,7 @@ To invoke a tool (for example `review`), you can run directly from the Docker im If you have a dedicated GitLab instance, you need to specify the custom url as variable: ``` - -e GITLAB.URL= + -e GITLAB.URL= ``` - For BitBucket: @@ -110,4 +110,4 @@ python3 -m pr_agent.cli --issue_url similar_issue [Optional] Add the pr_agent folder to your PYTHONPATH ``` export PYTHONPATH=$PYTHONPATH: -``` \ No newline at end of file +``` diff --git a/docs/docs/installation/pr_agent_pro.md b/docs/docs/installation/pr_agent_pro.md index 0fe870e7d..52fc92af2 100644 --- a/docs/docs/installation/pr_agent_pro.md +++ b/docs/docs/installation/pr_agent_pro.md @@ -4,12 +4,12 @@ Qodo Merge Pro is a versatile application compatible with GitHub, GitLab, and BitBucket, hosted by CodiumAI. See [here](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/) for more details about the benefits of using Qodo Merge Pro. -Interested parties can subscribe to Qodo Merge Pro through the following [link](https://www.codium.ai/pricing/). +Interested parties can subscribe to Qodo Merge Pro through the following [link](https://www.codium.ai/pricing/). After subscribing, you are granted the ability to easily install the application across any of your repositories. ![Qodo Merge Pro](https://codium.ai/images/pr_agent/pr_agent_pro_install.png){width=468} -Each user who wants to use Qodo Merge pro needs to buy a seat. +Each user who wants to use Qodo Merge pro needs to buy a seat. Initially, CodiumAI offers a two-week trial period at no cost, after which continued access requires each user to secure a personal seat. Once a user acquires a seat, they gain the flexibility to use Qodo Merge Pro across any repository where it was enabled. @@ -65,4 +65,4 @@ Enable SSL verification: Check the box. Youโ€™re all set! -Open a new merge request or add a MR comment with one of Qodo Mergeโ€™s commands such as /review, /describe or /improve. \ No newline at end of file +Open a new merge request or add a MR comment with one of Qodo Mergeโ€™s commands such as /review, /describe or /improve. diff --git a/docs/docs/overview/index.md b/docs/docs/overview/index.md index f56783bc8..2856cc1eb 100644 --- a/docs/docs/overview/index.md +++ b/docs/docs/overview/index.md @@ -90,4 +90,4 @@ The following diagram illustrates Qodo Merge tools and their flow: ![Qodo Merge Tools](https://codium.ai/images/pr_agent/diagram-v0.9.png) -Check out the [PR Compression strategy](core-abilities/index.md) page for more details on how we convert a code diff to a manageable LLM prompt \ No newline at end of file +Check out the [PR Compression strategy](core-abilities/index.md) page for more details on how we convert a code diff to a manageable LLM prompt diff --git a/docs/docs/overview/pr_agent_pro.md b/docs/docs/overview/pr_agent_pro.md index aa98add71..c22677749 100644 --- a/docs/docs/overview/pr_agent_pro.md +++ b/docs/docs/overview/pr_agent_pro.md @@ -19,7 +19,7 @@ Here are some of the additional features and capabilities that Qodo Merge Pro of | Feature | Description | |----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [**Model selection**](https://qodo-merge-docs.qodo.ai/usage-guide/PR_agent_pro_models/) | Choose the model that best fits your needs, among top models like `GPT4` and `Claude-Sonnet-3.5` +| [**Model selection**](https://qodo-merge-docs.qodo.ai/usage-guide/PR_agent_pro_models/) | Choose the model that best fits your needs, among top models like `GPT4` and `Claude-Sonnet-3.5` | [**Global and wiki configuration**](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/) | Control configurations for many repositories from a single location;
Edit configuration of a single repo without committing code | | [**Apply suggestions**](https://qodo-merge-docs.qodo.ai/tools/improve/#overview) | Generate committable code from the relevant suggestions interactively by clicking on a checkbox | | [**Suggestions impact**](https://qodo-merge-docs.qodo.ai/tools/improve/#assessing-impact) | Automatically mark suggestions that were implemented by the user (either directly in GitHub, or indirectly in the IDE) to enable tracking of the impact of the suggestions | @@ -45,7 +45,7 @@ Here are additional tools that are available only for Qodo Merge Pro users: ### Supported languages -Qodo Merge Pro leverages the world's leading code models - Claude 3.5 Sonnet and GPT-4. +Qodo Merge Pro leverages the world's leading code models - Claude 3.5 Sonnet and GPT-4. As a result, its primary tools such as `describe`, `review`, and `improve`, as well as the PR-chat feature, support virtually all programming languages. For specialized commands that require static code analysis, Qodo Merge Pro offers support for specific languages. For more details about features that require static code analysis, please refer to the [documentation](https://qodo-merge-docs.qodo.ai/tools/analyze/#overview). diff --git a/docs/docs/tools/analyze.md b/docs/docs/tools/analyze.md index 05458b132..c23d4418c 100644 --- a/docs/docs/tools/analyze.md +++ b/docs/docs/tools/analyze.md @@ -16,4 +16,4 @@ An example result: **Notes** -- Language that are currently supported: Python, Java, C++, JavaScript, TypeScript, C#. \ No newline at end of file +- Language that are currently supported: Python, Java, C++, JavaScript, TypeScript, C#. diff --git a/docs/docs/tools/ask.md b/docs/docs/tools/ask.md index fca5b7254..d29d03194 100644 --- a/docs/docs/tools/ask.md +++ b/docs/docs/tools/ask.md @@ -16,7 +16,7 @@ It can be invoked manually by commenting on any PR: You can run `/ask` on specific lines of code in the PR from the PR's diff view. The tool will answer questions based on the code changes in the selected lines. - Click on the '+' sign next to the line number to select the line. -- 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. ![Ask Line](https://codium.ai/images/pr_agent/Ask_line.png){width=512} @@ -56,4 +56,4 @@ To get a direct link to an image, we recommend using the following scheme: ![Ask image5](https://codium.ai/images/pr_agent/ask_images5.png){width=512} -See a full video tutorial [here](https://codium.ai/images/pr_agent/ask_image_video.mov) \ No newline at end of file +See a full video tutorial [here](https://codium.ai/images/pr_agent/ask_image_video.mov) diff --git a/docs/docs/tools/custom_labels.md b/docs/docs/tools/custom_labels.md index 86b4d6716..6df57f905 100644 --- a/docs/docs/tools/custom_labels.md +++ b/docs/docs/tools/custom_labels.md @@ -28,7 +28,7 @@ When working from CLI, you need to apply the [configuration changes](#configurat To enable custom labels, you need to apply the [configuration changes](#configuration-options) to the local `.pr_agent.toml` file in your repository. #### 3. Handle custom labels from the Repo's labels page ๐Ÿ’Ž -> This feature is available only in Qodo Merge Pro +> This feature is available only in Qodo Merge Pro * GitHub : `https://github.com/{owner}/{repo}/labels`, or click on the "Labels" tab in the issues or PRs page. * GitLab : `https://gitlab.com/{owner}/{repo}/-/labels`, or click on "Manage" -> "Labels" on the left menu. diff --git a/docs/docs/tools/custom_prompt.md b/docs/docs/tools/custom_prompt.md index 675bed695..9baa73d94 100644 --- a/docs/docs/tools/custom_prompt.md +++ b/docs/docs/tools/custom_prompt.md @@ -41,7 +41,7 @@ The code suggestions should focus only on the following: - make sure every variable has a meaningful name - make sure the code is efficient """ -``` +``` (The instructions above are just an example. We want to emphasize that the prompt should be specific and clear, and be tailored to the needs of your project) @@ -55,4 +55,4 @@ Results obtained with the prompt above: `num_code_suggestions`: number of code suggestions provided by the 'custom_prompt' tool. Default is 4. -`enable_help_text`: if set to true, the tool will display a help text in the comment. Default is true. \ No newline at end of file +`enable_help_text`: if set to true, the tool will display a help text in the comment. Default is true. diff --git a/docs/docs/tools/documentation.md b/docs/docs/tools/documentation.md index bb1330d16..12832b8d2 100644 --- a/docs/docs/tools/documentation.md +++ b/docs/docs/tools/documentation.md @@ -30,4 +30,4 @@ You can state a name of a specific component in the PR to get documentation only **Notes** - Language that are currently fully supported: Python, Java, C++, JavaScript, TypeScript, C#. -- This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool. \ No newline at end of file +- This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool. diff --git a/docs/docs/tools/improve.md b/docs/docs/tools/improve.md index 0b1ff8e58..bbc98e4a2 100644 --- a/docs/docs/tools/improve.md +++ b/docs/docs/tools/improve.md @@ -83,15 +83,15 @@ This feature is controlled by a boolean configuration parameter: `pr_code_sugges !!! note "Wiki must be enabled" While the aggregation process is automatic, GitHub repositories require a one-time manual wiki setup. - - To initialize the wiki: navigate to `Wiki`, select `Create the first page`, then click `Save page`. + + To initialize the wiki: navigate to `Wiki`, select `Create the first page`, then click `Save page`. ![pr_agent_accepted_suggestions_create_first_page.png](https://qodo.ai/images/pr_agent/pr_agent_accepted_suggestions_create_first_page.png){width=768} Once a wiki repo is created, the tool will automatically use this wiki for tracking suggestions. !!! note "Why a wiki page?" - Your code belongs to you, and we respect your privacy. Hence, we won't store any code suggestions in an external database. + Your code belongs to you, and we respect your privacy. Hence, we won't store any code suggestions in an external database. Instead, we leverage a dedicated private page, within your repository wiki, to track suggestions. This approach offers convenient secure suggestion tracking while avoiding pull requests or any noise to the main repository. @@ -109,10 +109,10 @@ In addition to mistakes (which may happen, but are rare), sometimes the presente In such cases, we recommend prioritizing the suggestion's detailed description, using the diff snippet primarily as a supporting reference. ### Dual publishing mode -Our recommended approach for presenting code suggestions is through a [table](https://qodo-merge-docs.qodo.ai/tools/improve/#overview) (`--pr_code_suggestions.commitable_code_suggestions=false`). +Our recommended approach for presenting code suggestions is through a [table](https://qodo-merge-docs.qodo.ai/tools/improve/#overview) (`--pr_code_suggestions.commitable_code_suggestions=false`). This method significantly reduces the PR footprint and allows for quick and easy digestion of multiple suggestions. -We also offer a complementary **dual publishing mode**. When enabled, suggestions exceeding a certain score threshold are not only displayed in the table, but also presented as commitable PR comments. +We also offer a complementary **dual publishing mode**. When enabled, suggestions exceeding a certain score threshold are not only displayed in the table, but also presented as commitable PR comments. This mode helps highlight suggestions deemed more critical. To activate dual publishing mode, use the following setting: @@ -165,9 +165,9 @@ code_suggestions_self_review_text = "... (your text here) ..." ![self_review_2](https://codium.ai/images/pr_agent/self_review_2.png){width=512} - If you keep the number of required reviewers for a PR to 1 and enable this configuration, this effectively means that the PR author can approve the PR by actively clicking the self-review checkbox. - + To prevent unauthorized approvals, this configuration defaults to false, and cannot be altered through online comments; enabling requires a direct update to the configuration file and a commit to the repository. This ensures that utilizing the feature demands a deliberate documented decision by the repository owner. - + ### How many code suggestions are generated? Qodo Merge uses a dynamic strategy to generate code suggestions based on the size of the pull request (PR). Here's how it works: @@ -199,7 +199,7 @@ Note: Chunking is primarily relevant for large PRs. For most PRs (up to 500 line You can use the `extra_instructions` configuration option to give the AI model additional instructions for the `improve` tool. Be specific, clear, and concise in the instructions. With extra instructions, you are the prompter. Specify relevant aspects that you want the model to focus on. - + Examples for possible instructions: ```toml [pr_code_suggestions] @@ -216,11 +216,11 @@ Use triple quotes to write multi-line instructions. Use bullet points or numbers >`Platforms supported: GitHub, GitLab` -Another option to give additional guidance to the AI model is by creating a dedicated [**wiki page**](https://github.com/Codium-ai/pr-agent/wiki) called `best_practices.md`. +Another option to give additional guidance to the AI model is by creating a dedicated [**wiki page**](https://github.com/Codium-ai/pr-agent/wiki) called `best_practices.md`. This page can contain a list of best practices, coding standards, and guidelines that are specific to your repo/organization. The AI model will use this wiki page as a reference, and in case the PR code violates any of the guidelines, it will suggest improvements accordingly, with a dedicated label: `Organization -best practice`. +best practice`. Example for a `best_practices.md` content can be found [here](https://github.com/Codium-ai/pr-agent/blob/main/docs/docs/usage-guide/EXAMPLE_BEST_PRACTICE.md) (adapted from Google's [pyguide](https://google.github.io/styleguide/pyguide.html)). This file is only an example. Since it is used as a prompt for an AI model, we want to emphasize the following: @@ -230,7 +230,7 @@ This file is only an example. Since it is used as a prompt for an AI model, we w - Recommended to limit the text to 800 lines or fewer. Hereโ€™s why: 1) Extremely long best practices documents may not be fully processed by the AI model. - + 2) A lengthy file probably represent a more "**generic**" set of guidelines, which the AI model is already familiar with. The objective is to focus on a more targeted set of guidelines tailored to the specific needs of this project. ##### Local and global best practices @@ -261,7 +261,7 @@ Using a combination of both can help the AI model to provide relevant and tailor ## Configuration options ??? example "General options" - + @@ -335,5 +335,5 @@ Using a combination of both can help the AI model to provide relevant and tailor - Only if the `Category` header is relevant, the user should move to the summarized suggestion description - Only if the summarized suggestion description is relevant, the user should click on the collapsible, to read the full suggestion description with a code preview example. -- In addition, we recommend to use the [`extra_instructions`](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices) field to guide the model to suggestions that are more relevant to the specific needs of the project. +- In addition, we recommend to use the [`extra_instructions`](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices) field to guide the model to suggestions that are more relevant to the specific needs of the project. - The interactive [PR chat](https://qodo-merge-docs.qodo.ai/chrome-extension/) also provides an easy way to get more tailored suggestions and feedback from the AI model. diff --git a/docs/docs/tools/improve_component.md b/docs/docs/tools/improve_component.md index 4e0c88902..b3aac5392 100644 --- a/docs/docs/tools/improve_component.md +++ b/docs/docs/tools/improve_component.md @@ -26,4 +26,4 @@ The tool will generate code suggestions for the selected component (if no compon - `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. \ No newline at end of file +- `class_name`: in case there are several methods with the same name in the same file, you can specify the relevant class name. diff --git a/docs/docs/tools/index.md b/docs/docs/tools/index.md index 394bdbabf..9b856e23d 100644 --- a/docs/docs/tools/index.md +++ b/docs/docs/tools/index.md @@ -19,4 +19,4 @@ Here is a list of Qodo Merge tools, each with a dedicated page that explains how | **๐Ÿ’Ž [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 Qodo Merge Pro users. \ No newline at end of file +Note that the tools marked with ๐Ÿ’Ž are available only for Qodo Merge Pro users. diff --git a/docs/docs/tools/review.md b/docs/docs/tools/review.md index 2fd774f6e..5d70c9e45 100644 --- a/docs/docs/tools/review.md +++ b/docs/docs/tools/review.md @@ -180,10 +180,10 @@ If enabled, the `review` tool can approve a PR when a specific comment, `/review The `review` tool provides a collection of configurable feedbacks about a PR. It is recommended to review the [Configuration options](#configuration-options) section, and choose the relevant options for your use case. - - Some of the features that are disabled by default are quite useful, and should be considered for enabling. For example: + + Some of the features that are disabled by default are quite useful, and should be considered for enabling. For example: `require_score_review`, and more. - + On the other hand, if you find one of the enabled features to be irrelevant for your use case, disable it. No default configuration can fit all use cases. !!! tip "Automation" @@ -197,19 +197,19 @@ If enabled, the `review` tool can approve a PR when a specific comment, `/review !!! tip "Possible labels from the review tool" The `review` tool can auto-generate two specific types of labels for a PR: - + - a `possible security issue` label that detects if a possible [security issue](https://github.com/Codium-ai/pr-agent/blob/tr/user_description/pr_agent/settings/pr_reviewer_prompts.toml#L136) exists in the PR code (`enable_review_labels_security` flag) - a `Review effort [1-5]: x` label, where x is the estimated effort to review the PR (`enable_review_labels_effort` flag) - + Both modes are useful, and we recommended to enable them. !!! tip "Extra instructions" Extra instructions are important. The `review` tool can be configured with extra instructions, which can be used to guide the model to a feedback tailored to the needs of your project. - + Be specific, clear, and concise in the instructions. With extra instructions, you are the prompter. Specify the relevant sub-tool, and the relevant aspects of the PR that you want to emphasize. - + Examples of extra instructions: ``` [pr_reviewer] @@ -227,22 +227,22 @@ If enabled, the `review` tool can approve a PR when a specific comment, `/review !!! tip "Auto-approval" Qodo Merge can approve a PR when a specific comment is invoked. - + To ensure safety, the auto-approval feature is disabled by default. To enable auto-approval, you need to actively set in a pre-defined configuration file the following: ``` [pr_reviewer] enable_auto_approval = true ``` (this specific flag cannot be set with a command line argument, only in the configuration file, committed to the repository) - - + + After enabling, by commenting on a PR: ``` /review auto_approve ``` Qodo Merge will automatically approve the PR, and add a comment with the approval. - - + + You can also enable auto-approval only if the PR meets certain requirements, such as that the `estimated_review_effort` label is equal or below a certain threshold, by adjusting the flag: ``` [pr_reviewer] @@ -258,4 +258,3 @@ If enabled, the `review` tool can approve a PR when a specific comment, `/review [//]: # ( Notice If you are interested **only** in the code suggestions, it is recommended to use the [`improve`](./improve.md) feature instead, since it is a dedicated only to code suggestions, and usually gives better results.) [//]: # ( Use the `review` tool if you want to get more comprehensive feedback, which includes code suggestions as well.) - diff --git a/docs/docs/tools/similar_code.md b/docs/docs/tools/similar_code.md index c992a2627..11de3a0cd 100644 --- a/docs/docs/tools/similar_code.md +++ b/docs/docs/tools/similar_code.md @@ -51,7 +51,7 @@ It can be invoked automatically from the analyze table, can be accessed by: Choose the components you want to find similar code for, and click on the `similar` checkbox. ![analyze similar](https://codium.ai/images/pr_agent/analyze_similar.png){width=768} -If you are looking to search for similar code in the organization's codebase, you can click on the `Organization` checkbox, and it will invoke a new search command just for the organization's codebase. +If you are looking to search for similar code in the organization's codebase, you can click on the `Organization` checkbox, and it will invoke a new search command just for the organization's codebase. ![similar code global](https://codium.ai/images/pr_agent/similar_code_global.png){width=768} diff --git a/docs/docs/tools/similar_issues.md b/docs/docs/tools/similar_issues.md index 4f0351e0d..d701c1c68 100644 --- a/docs/docs/tools/similar_issues.md +++ b/docs/docs/tools/similar_issues.md @@ -17,7 +17,7 @@ It can be invoked manually by commenting on any PR: Note that to perform retrieval, the `similar_issue` tool indexes all the repo previous issues (once). -**Select VectorDBs** by changing `pr_similar_issue` parameter in `configuration.toml` file +**Select VectorDBs** by changing `pr_similar_issue` parameter in `configuration.toml` file 2 VectorDBs are available to switch in 1. LanceDB @@ -40,4 +40,4 @@ These parameters can be obtained by registering to [Pinecone](https://app.pineco - To invoke the 'similar' issue tool via online usage, [comment](https://github.com/Codium-ai/pr-agent/issues/178#issuecomment-1716934893) on a PR: `/similar_issue` -- You can also enable the 'similar issue' tool to run automatically when a new issue is opened, by adding it to the [pr_commands list in the github_app section](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L66) \ No newline at end of file +- You can also enable the 'similar issue' tool to run automatically when a new issue is opened, by adding it to the [pr_commands list in the github_app section](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L66) diff --git a/docs/docs/tools/test.md b/docs/docs/tools/test.md index b5a143f06..f3cc39103 100644 --- a/docs/docs/tools/test.md +++ b/docs/docs/tools/test.md @@ -29,4 +29,4 @@ The tool will generate tests for the selected component (if no component is stat - `extra_instructions`: Optional extra instructions to the tool. For example: "use the following mock injection scheme: ...". - `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. -- `enable_help_text`: if set to true, the tool will add a help text to the PR comment. Default is true. \ No newline at end of file +- `enable_help_text`: if set to true, the tool will add a help text to the PR comment. Default is true. diff --git a/docs/docs/tools/update_changelog.md b/docs/docs/tools/update_changelog.md index 0c1bfda55..9f880ccdf 100644 --- a/docs/docs/tools/update_changelog.md +++ b/docs/docs/tools/update_changelog.md @@ -16,4 +16,4 @@ It can be invoked manually by commenting on any PR: Under the section `pr_update_changelog`, the [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L50) contains options to customize the 'update changelog' tool: - `push_changelog_changes`: whether to push the changes to CHANGELOG.md, or just print them. Default is false (print only). -- `extra_instructions`: Optional extra instructions to the tool. For example: "focus on the changes in the file X. Ignore change in ... \ No newline at end of file +- `extra_instructions`: Optional extra instructions to the tool. For example: "focus on the changes in the file X. Ignore change in ... diff --git a/docs/docs/usage-guide/EXAMPLE_BEST_PRACTICE.md b/docs/docs/usage-guide/EXAMPLE_BEST_PRACTICE.md index 0ec886a65..e9de20d8f 100644 --- a/docs/docs/usage-guide/EXAMPLE_BEST_PRACTICE.md +++ b/docs/docs/usage-guide/EXAMPLE_BEST_PRACTICE.md @@ -186,4 +186,4 @@ Do not rely on the atomicity of built-in types. While Pythonโ€™s built-in data types such as dictionaries appear to have atomic operations, there are corner cases where they arenโ€™t atomic (e.g. if `__hash__` or `__eq__` are implemented as Python methods) and their atomicity should not be relied upon. Neither should you rely on atomic variable assignment (since this in turn depends on dictionaries). -Use the `queue` moduleโ€™s `Queue` data type as the preferred way to communicate data between threads. Otherwise, use the `threading` module and its locking primitives. Prefer condition variables and `threading.Condition` instead of using lower-level locks. \ No newline at end of file +Use the `queue` moduleโ€™s `Queue` data type as the preferred way to communicate data between threads. Otherwise, use the `threading` module and its locking primitives. Prefer condition variables and `threading.Condition` instead of using lower-level locks. diff --git a/docs/docs/usage-guide/automations_and_usage.md b/docs/docs/usage-guide/automations_and_usage.md index 57e1adeb5..6fca67ec3 100644 --- a/docs/docs/usage-guide/automations_and_usage.md +++ b/docs/docs/usage-guide/automations_and_usage.md @@ -66,7 +66,7 @@ Any configuration value in [configuration file](https://github.com/Codium-ai/pr- ### 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. The configuration parameter `pr_commands` defines the list of tools that will be **run automatically** when a new PR is opened. ``` @@ -77,10 +77,10 @@ pr_commands = [ "/improve", ] ``` -This means that when a new PR is opened/reopened or marked as ready for review, Qodo Merge will run the `describe`, `review` and `improve` tools. +This means that when a new PR is opened/reopened or marked as ready for review, Qodo Merge will run the `describe`, `review` and `improve` tools. For the `review` tool, for example, the `num_code_suggestions` parameter will be set to 0. -You can override the default tool parameters by using one the three options for a [configuration file](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/): **wiki**, **local**, or **global**. +You can override the default tool parameters by using one the three options for a [configuration file](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/): **wiki**, **local**, or **global**. For example, if your local `.pr_agent.toml` file contains: ``` [pr_description] @@ -98,7 +98,7 @@ pr_commands = [] In addition to running automatic tools when a PR is opened, the GitHub app can also respond to new code that is pushed to an open PR. -The configuration toggle `handle_push_trigger` can be used to enable this feature. +The configuration toggle `handle_push_trigger` can be used to enable this feature. The configuration parameter `push_commands` defines the list of tools that will be **run automatically** when new code is pushed to the PR. ``` [github_app] @@ -112,7 +112,7 @@ This means that when new code is pushed to the PR, the Qodo Merge will run the ` ## GitHub Action `GitHub Action` is a different way to trigger Qodo Merge tools, and uses a different configuration mechanism than `GitHub App`.
-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: ```yaml env: @@ -129,7 +129,7 @@ If not set, the default configuration is for all three tools to run automaticall `github_action_config.pr_actions` is used to configure which `pull_requests` events will trigger the enabled auto flags If not set, the default configuration is `["opened", "reopened", "ready_for_review", "review_requested"]` -`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`). +`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). @@ -154,7 +154,7 @@ pr_commands = [ ``` the GitLab webhook can also respond to new code that is pushed to an open MR. -The configuration toggle `handle_push_trigger` can be used to enable this feature. +The configuration toggle `handle_push_trigger` can be used to enable this feature. The configuration parameter `push_commands` defines the list of tools that will be **run automatically** when new code is pushed to the MR. ``` [gitlab] @@ -210,11 +210,11 @@ git_provider="azure" ``` Azure DevOps provider supports [PAT token](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=Windows) or [DefaultAzureCredential](https://learn.microsoft.com/en-us/azure/developer/python/sdk/authentication-overview#authentication-in-server-environments) authentication. -PAT is faster to create, but has build in expiration date, and will use the user identity for API calls. +PAT is faster to create, but has build in expiration date, and will use the user identity for API calls. Using DefaultAzureCredential you can use managed identity or Service principle, which are more secure and will create separate ADO user identity (via AAD) to the agent. -If PAT was chosen, you can assign the value in .secrets.toml. -If DefaultAzureCredential was chosen, you can assigned the additional env vars like AZURE_CLIENT_SECRET directly, +If PAT was chosen, you can assign the value in .secrets.toml. +If DefaultAzureCredential was chosen, you can assigned the additional env vars like AZURE_CLIENT_SECRET directly, or use managed identity/az cli (for local development) without any additional configuration. in any case, 'org' value must be assigned in .secrets.toml: ``` diff --git a/docs/docs/usage-guide/changing_a_model.md b/docs/docs/usage-guide/changing_a_model.md index f214f7168..d5f6ae03f 100644 --- a/docs/docs/usage-guide/changing_a_model.md +++ b/docs/docs/usage-guide/changing_a_model.md @@ -9,7 +9,7 @@ model_turbo = "..." fallback_models = ["..."] ``` -For models and environments not from OpenAI, you might need to provide additional keys and other parameters. +For models and environments not from OpenAI, you might need to provide additional keys and other parameters. You can give parameters via a configuration file (see below for instructions), or from environment variables. See [litellm documentation](https://litellm.vercel.app/docs/proxy/quick_start#supported-llms) for the environment variables relevant per model. ### Azure @@ -108,7 +108,7 @@ To use Llama3 model with Groq, for example, set: [config] # in configuration.toml model = "llama3-70b-8192" model_turbo = "llama3-70b-8192" -fallback_models = ["groq/llama3-70b-8192"] +fallback_models = ["groq/llama3-70b-8192"] [groq] # in .secrets.toml key = ... # your Groq api key ``` @@ -118,7 +118,7 @@ key = ... # your Groq api key To use Google's Vertex AI platform and its associated models (chat-bison/codechat-bison) set: -``` +``` [config] # in configuration.toml model = "vertex_ai/codechat-bison" model_turbo = "vertex_ai/codechat-bison" @@ -170,7 +170,7 @@ KEY = "..." To use Amazon Bedrock and its foundational models, add the below configuration: -``` +``` [config] # in configuration.toml model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0" model_turbo="bedrock/anthropic.claude-3-sonnet-20240229-v1:0" diff --git a/docs/docs/usage-guide/configuration_options.md b/docs/docs/usage-guide/configuration_options.md index 7b5607b71..c97b6531c 100644 --- a/docs/docs/usage-guide/configuration_options.md +++ b/docs/docs/usage-guide/configuration_options.md @@ -20,7 +20,7 @@ In terms of precedence, wiki configurations will override local configurations, `Platforms supported: GitHub, GitLab, Bitbucket` -With Qodo Merge Pro, you can set configurations by creating a page called `.pr_agent.toml` in the [wiki](https://github.com/Codium-ai/pr-agent/wiki/pr_agent.toml) of the repo. +With Qodo Merge Pro, you can set configurations by creating a page called `.pr_agent.toml` in the [wiki](https://github.com/Codium-ai/pr-agent/wiki/pr_agent.toml) of the repo. The advantage of this method is that it allows to set configurations without needing to commit new content to the repo - just edit the wiki page and **save**. diff --git a/docs/docs/usage-guide/index.md b/docs/docs/usage-guide/index.md index bd1b93f49..1b680d8c0 100644 --- a/docs/docs/usage-guide/index.md +++ b/docs/docs/usage-guide/index.md @@ -1,6 +1,6 @@ # Usage guide -This page provides a detailed guide on how to use Qodo Merge. +This page provides a detailed guide on how to use Qodo Merge. It includes information on how to adjust Qodo Merge configurations, define which tools will run automatically, and other advanced configurations. @@ -23,4 +23,4 @@ It includes information on how to adjust Qodo Merge configurations, define which - [Changing a model](./additional_configurations.md#changing-a-model) - [Patch Extra Lines](./additional_configurations.md#patch-extra-lines) - [Editing the prompts](./additional_configurations.md#editing-the-prompts) -- [Qodo Merge Pro Models](./PR_agent_pro_models.md) \ No newline at end of file +- [Qodo Merge Pro Models](./PR_agent_pro_models.md) diff --git a/docs/docs/usage-guide/introduction.md b/docs/docs/usage-guide/introduction.md index 687500a4e..521ce6d7c 100644 --- a/docs/docs/usage-guide/introduction.md +++ b/docs/docs/usage-guide/introduction.md @@ -10,4 +10,3 @@ Specifically, CLI commands can be issued by invoking a pre-built [docker image]( For online usage, you will need to setup either a [GitHub App](https://qodo-merge-docs.qodo.ai/installation/github/#run-as-a-github-app) or a [GitHub Action](https://qodo-merge-docs.qodo.ai/installation/github/#run-as-a-github-action) (GitHub), a [GitLab webhook](https://qodo-merge-docs.qodo.ai/installation/gitlab/#run-a-gitlab-webhook-server) (GitLab), or a [BitBucket App](https://qodo-merge-docs.qodo.ai/installation/bitbucket/#run-using-codiumai-hosted-bitbucket-app) (BitBucket). These platforms also enable to run Qodo Merge specific tools automatically when a new PR is opened, or on each push to a branch. - diff --git a/docs/docs/usage-guide/mail_notifications.md b/docs/docs/usage-guide/mail_notifications.md index 42fd7a8d1..a1d97016d 100644 --- a/docs/docs/usage-guide/mail_notifications.md +++ b/docs/docs/usage-guide/mail_notifications.md @@ -9,10 +9,10 @@ As an alternative, you can filter in your mail provider the notifications specif ![filter_mail_notifications](https://codium.ai/images/pr_agent/filter_mail_notifications.png){width=512} -Another option to reduce the mail overload, yet still receive notifications on Qodo Merge tools, is to disable the help collapsible section in Qodo Merge bot comments. +Another option to reduce the mail overload, yet still receive notifications on Qodo Merge tools, is to disable the help collapsible section in Qodo Merge 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 -``` \ No newline at end of file +``` diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index f6957536a..53ae3c24e 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -144,8 +144,8 @@ markdown_extensions: - md_in_html - attr_list - pymdownx.emoji: - emoji_index: !!python/name:material.extensions.emoji.twemoji - emoji_generator: !!python/name:material.extensions.emoji.to_svg + emoji_index: "!!python/name:material.extensions.emoji.twemoji" + emoji_generator: "!!python/name:material.extensions.emoji.to_svg" - toc: title: On this page toc_depth: 3 diff --git a/docs/overrides/main.html b/docs/overrides/main.html index 93a67950d..2f0de5aea 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -2,9 +2,9 @@ {% block scripts %} {{ super() }} - + -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/docs/overrides/partials/footer.html b/docs/overrides/partials/footer.html index e41686ac4..23f408943 100644 --- a/docs/overrides/partials/footer.html +++ b/docs/overrides/partials/footer.html @@ -42,7 +42,7 @@ } .social-icons svg { - width: 24px; + width: 24px; height: auto; fill: white; } diff --git a/docs/overrides/partials/integrations/analytics/custom.html b/docs/overrides/partials/integrations/analytics/custom.html index 9a0785d2a..63dc6503a 100644 --- a/docs/overrides/partials/integrations/analytics/custom.html +++ b/docs/overrides/partials/integrations/analytics/custom.html @@ -4,4 +4,4 @@ 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'); - \ No newline at end of file + diff --git a/pr_agent/__init__.py b/pr_agent/__init__.py index 8b1378917..e69de29bb 100644 --- a/pr_agent/__init__.py +++ b/pr_agent/__init__.py @@ -1 +0,0 @@ - diff --git a/pr_agent/agent/pr_agent.py b/pr_agent/agent/pr_agent.py index 8bf6cff75..d16e7a5ca 100644 --- a/pr_agent/agent/pr_agent.py +++ b/pr_agent/agent/pr_agent.py @@ -3,7 +3,6 @@ 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.utils import update_settings_from_args from pr_agent.config_loader import get_settings from pr_agent.git_providers.utils import apply_repo_settings diff --git a/pr_agent/algo/ai_handlers/base_ai_handler.py b/pr_agent/algo/ai_handlers/base_ai_handler.py index e3274eac4..956fcaffd 100644 --- a/pr_agent/algo/ai_handlers/base_ai_handler.py +++ b/pr_agent/algo/ai_handlers/base_ai_handler.py @@ -3,7 +3,7 @@ class BaseAiHandler(ABC): """ - This class defines the interface for an AI handler to be used by the PR Agents. + This class defines the interface for an AI handler to be used by the PR Agents. """ @abstractmethod @@ -23,6 +23,6 @@ async def chat_completion(self, model: str, system: str, user: str, temperature: model (str): the name of the model to use for the chat completion system (str): the system message string to use for the chat completion user (str): the user message string to use for the chat completion - temperature (float): the temperature to use for the chat completion + temperature (float): the temperature to use for the chat completion """ pass diff --git a/pr_agent/algo/ai_handlers/langchain_ai_handler.py b/pr_agent/algo/ai_handlers/langchain_ai_handler.py index 2f3b88c13..d4ea0aa5d 100644 --- a/pr_agent/algo/ai_handlers/langchain_ai_handler.py +++ b/pr_agent/algo/ai_handlers/langchain_ai_handler.py @@ -1,16 +1,17 @@ try: - from langchain_openai import ChatOpenAI, AzureChatOpenAI - from langchain_core.messages import SystemMessage, HumanMessage + from langchain_core.messages import HumanMessage, SystemMessage + from langchain_openai import AzureChatOpenAI, ChatOpenAI except: # we don't enforce langchain as a dependency, so if it's not installed, just move on pass -from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler -from pr_agent.config_loader import get_settings -from pr_agent.log import get_logger +import functools from openai import APIError, RateLimitError, Timeout from retry import retry -import functools + +from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler +from pr_agent.config_loader import get_settings +from pr_agent.log import get_logger OPENAI_RETRIES = 5 @@ -73,4 +74,3 @@ def _create_chat(self, deployment_id=None): raise ValueError(f"OpenAI {e.name} is required") from e else: raise e - diff --git a/pr_agent/algo/ai_handlers/litellm_ai_handler.py b/pr_agent/algo/ai_handlers/litellm_ai_handler.py index 882e23708..ad1fc5643 100644 --- a/pr_agent/algo/ai_handlers/litellm_ai_handler.py +++ b/pr_agent/algo/ai_handlers/litellm_ai_handler.py @@ -1,7 +1,8 @@ import os -import requests + import litellm import openai +import requests from litellm import acompletion from tenacity import retry, retry_if_exception_type, stop_after_attempt diff --git a/pr_agent/algo/ai_handlers/openai_ai_handler.py b/pr_agent/algo/ai_handlers/openai_ai_handler.py index 999f3d3fb..b235af960 100644 --- a/pr_agent/algo/ai_handlers/openai_ai_handler.py +++ b/pr_agent/algo/ai_handlers/openai_ai_handler.py @@ -1,8 +1,8 @@ -from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler import openai from openai.error import APIError, RateLimitError, Timeout, TryAgain from retry import retry +from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.config_loader import get_settings from pr_agent.log import get_logger diff --git a/pr_agent/algo/git_patch_processing.py b/pr_agent/algo/git_patch_processing.py index f0540ad0a..0ccce92d7 100644 --- a/pr_agent/algo/git_patch_processing.py +++ b/pr_agent/algo/git_patch_processing.py @@ -3,8 +3,8 @@ import re import traceback -from pr_agent.config_loader import get_settings from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo +from pr_agent.config_loader import get_settings from pr_agent.log import get_logger @@ -388,4 +388,4 @@ def extract_hunk_lines_from_patch(patch: str, file_name, line_start, line_end, s if not line.startswith('-'): # currently we don't support /ask line for deleted lines selected_lines_num += 1 - return patch_with_lines_str.rstrip(), selected_lines.rstrip() \ No newline at end of file + return patch_with_lines_str.rstrip(), selected_lines.rstrip() diff --git a/pr_agent/algo/language_handler.py b/pr_agent/algo/language_handler.py index 7c1039986..dea772603 100644 --- a/pr_agent/algo/language_handler.py +++ b/pr_agent/algo/language_handler.py @@ -4,8 +4,6 @@ from pr_agent.config_loader import get_settings - - def filter_bad_extensions(files): # Bad Extensions, source: https://github.com/EleutherAI/github-downloader/blob/345e7c4cbb9e0dc8a0615fd995a08bf9d73b3fe6/download_repo_text.py # noqa: E501 bad_extensions = get_settings().bad_extensions.default diff --git a/pr_agent/algo/pr_processing.py b/pr_agent/algo/pr_processing.py index 95d2fda72..114e24a09 100644 --- a/pr_agent/algo/pr_processing.py +++ b/pr_agent/algo/pr_processing.py @@ -5,14 +5,15 @@ from github import RateLimitExceededException -from pr_agent.algo.git_patch_processing import convert_to_hunks_with_lines_numbers, extend_patch, handle_patch_deletions -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.git_patch_processing import ( + convert_to_hunks_with_lines_numbers, extend_patch, handle_patch_deletions) +from pr_agent.algo.language_handler import sort_files_by_main_languages from pr_agent.algo.token_handler import TokenHandler -from pr_agent.algo.utils import get_max_tokens, clip_tokens, ModelType +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo +from pr_agent.algo.utils import ModelType, clip_tokens, get_max_tokens from pr_agent.config_loader import get_settings from pr_agent.git_providers.git_provider import GitProvider -from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from pr_agent.log import get_logger DELETED_FILES_ = "Deleted files:\n" diff --git a/pr_agent/algo/token_handler.py b/pr_agent/algo/token_handler.py index 935e6da5f..72f6184ec 100644 --- a/pr_agent/algo/token_handler.py +++ b/pr_agent/algo/token_handler.py @@ -1,8 +1,9 @@ +from threading import Lock + from jinja2 import Environment, StrictUndefined from tiktoken import encoding_for_model, get_encoding -from pr_agent.config_loader import get_settings -from threading import Lock +from pr_agent.config_loader import get_settings from pr_agent.log import get_logger @@ -85,4 +86,4 @@ def count_tokens(self, patch: str) -> int: Returns: The number of tokens in the patch string. """ - return len(self.encoder.encode(patch, disallowed_special=())) \ No newline at end of file + return len(self.encoder.encode(patch, disallowed_special=())) diff --git a/pr_agent/algo/utils.py b/pr_agent/algo/utils.py index 6a23d609f..a90636d3c 100644 --- a/pr_agent/algo/utils.py +++ b/pr_agent/algo/utils.py @@ -14,7 +14,6 @@ from enum import Enum from typing import Any, List, Tuple - import html2text import requests import yaml @@ -23,10 +22,11 @@ from pr_agent.algo import MAX_TOKENS from pr_agent.algo.token_handler import TokenEncoder -from pr_agent.config_loader import get_settings, global_settings from pr_agent.algo.types import FilePatchInfo +from pr_agent.config_loader import get_settings, global_settings from pr_agent.log import get_logger + class Range(BaseModel): line_start: int # should be 0-indexed line_end: int diff --git a/pr_agent/cli.py b/pr_agent/cli.py index 98b493ded..5f8afc885 100644 --- a/pr_agent/cli.py +++ b/pr_agent/cli.py @@ -4,7 +4,7 @@ from pr_agent.agent.pr_agent import PRAgent, commands from pr_agent.config_loader import get_settings -from pr_agent.log import setup_logger, get_logger +from pr_agent.log import get_logger, setup_logger log_level = os.environ.get("LOG_LEVEL", "INFO") setup_logger(log_level) diff --git a/pr_agent/git_providers/__init__.py b/pr_agent/git_providers/__init__.py index c7e3e6e81..16547d90c 100644 --- a/pr_agent/git_providers/__init__.py +++ b/pr_agent/git_providers/__init__.py @@ -1,14 +1,16 @@ +from starlette_context import context + from pr_agent.config_loader import get_settings +from pr_agent.git_providers.azuredevops_provider import AzureDevopsProvider from pr_agent.git_providers.bitbucket_provider import BitbucketProvider -from pr_agent.git_providers.bitbucket_server_provider import BitbucketServerProvider +from pr_agent.git_providers.bitbucket_server_provider import \ + BitbucketServerProvider from pr_agent.git_providers.codecommit_provider import CodeCommitProvider +from pr_agent.git_providers.gerrit_provider import GerritProvider from pr_agent.git_providers.git_provider import GitProvider from pr_agent.git_providers.github_provider import GithubProvider from pr_agent.git_providers.gitlab_provider import GitLabProvider from pr_agent.git_providers.local_git_provider import LocalGitProvider -from pr_agent.git_providers.azuredevops_provider import AzureDevopsProvider -from pr_agent.git_providers.gerrit_provider import GerritProvider -from starlette_context import context _GIT_PROVIDERS = { 'github': GithubProvider, diff --git a/pr_agent/git_providers/azuredevops_provider.py b/pr_agent/git_providers/azuredevops_provider.py index de7829988..df87c564e 100644 --- a/pr_agent/git_providers/azuredevops_provider.py +++ b/pr_agent/git_providers/azuredevops_provider.py @@ -2,13 +2,16 @@ from typing import Optional, Tuple from urllib.parse import urlparse +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo + from ..algo.file_filter import filter_ignored -from ..log import get_logger from ..algo.language_handler import is_valid_file -from ..algo.utils import clip_tokens, find_line_number_of_relevant_line_in_file, load_large_diff, PRDescriptionHeader +from ..algo.utils import (PRDescriptionHeader, clip_tokens, + find_line_number_of_relevant_line_in_file, + load_large_diff) from ..config_loader import get_settings +from ..log import get_logger from .git_provider import GitProvider -from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo AZURE_DEVOPS_AVAILABLE = True ADO_APP_CLIENT_DEFAULT_ID = "499b84ac-1321-427f-aa17-267ca6975798/.default" @@ -16,19 +19,16 @@ try: # noinspection PyUnresolvedReferences - from msrest.authentication import BasicAuthentication # noinspection PyUnresolvedReferences from azure.devops.connection import Connection # noinspection PyUnresolvedReferences - from azure.identity import DefaultAzureCredential + from azure.devops.v7_1.git.models import (Comment, CommentThread, + GitPullRequest, + GitPullRequestIterationChanges, + GitVersionDescriptor) # noinspection PyUnresolvedReferences - from azure.devops.v7_1.git.models import ( - Comment, - CommentThread, - GitVersionDescriptor, - GitPullRequest, - GitPullRequestIterationChanges, - ) + from azure.identity import DefaultAzureCredential + from msrest.authentication import BasicAuthentication except ImportError: AZURE_DEVOPS_AVAILABLE = False @@ -620,4 +620,3 @@ def get_pr_id(self): def publish_file_comments(self, file_comments: list) -> bool: pass - diff --git a/pr_agent/git_providers/bitbucket_provider.py b/pr_agent/git_providers/bitbucket_provider.py index 51ba07700..76313ddff 100644 --- a/pr_agent/git_providers/bitbucket_provider.py +++ b/pr_agent/git_providers/bitbucket_provider.py @@ -6,13 +6,14 @@ from atlassian.bitbucket import Cloud from starlette_context import context -from pr_agent.algo.types import FilePatchInfo, EDIT_TYPE +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo + from ..algo.file_filter import filter_ignored from ..algo.language_handler import is_valid_file from ..algo.utils import find_line_number_of_relevant_line_in_file from ..config_loader import get_settings from ..log import get_logger -from .git_provider import GitProvider, MAX_FILES_ALLOWED_FULL +from .git_provider import MAX_FILES_ALLOWED_FULL, GitProvider def _gef_filename(diff): diff --git a/pr_agent/git_providers/bitbucket_server_provider.py b/pr_agent/git_providers/bitbucket_server_provider.py index 7588075e5..5fb599e48 100644 --- a/pr_agent/git_providers/bitbucket_server_provider.py +++ b/pr_agent/git_providers/bitbucket_server_provider.py @@ -1,16 +1,17 @@ from distutils.version import LooseVersion -from requests.exceptions import HTTPError from typing import Optional, Tuple from urllib.parse import quote_plus, urlparse from atlassian.bitbucket import Bitbucket +from requests.exceptions import HTTPError -from .git_provider import GitProvider -from ..algo.types import EDIT_TYPE, FilePatchInfo from ..algo.language_handler import is_valid_file -from ..algo.utils import load_large_diff, find_line_number_of_relevant_line_in_file +from ..algo.types import EDIT_TYPE, FilePatchInfo +from ..algo.utils import (find_line_number_of_relevant_line_in_file, + load_large_diff) from ..config_loader import get_settings from ..log import get_logger +from .git_provider import GitProvider class BitbucketServerProvider(GitProvider): diff --git a/pr_agent/git_providers/codecommit_provider.py b/pr_agent/git_providers/codecommit_provider.py index 89a0254df..c4f1ed7bf 100644 --- a/pr_agent/git_providers/codecommit_provider.py +++ b/pr_agent/git_providers/codecommit_provider.py @@ -4,13 +4,15 @@ from typing import List, Optional, Tuple from urllib.parse import urlparse -from pr_agent.git_providers.codecommit_client import CodeCommitClient +from pr_agent.algo.language_handler import is_valid_file from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo +from pr_agent.git_providers.codecommit_client import CodeCommitClient + from ..algo.utils import load_large_diff -from .git_provider import GitProvider from ..config_loader import get_settings from ..log import get_logger -from pr_agent.algo.language_handler import is_valid_file +from .git_provider import GitProvider + class PullRequestCCMimic: """ @@ -162,7 +164,7 @@ def publish_description(self, pr_title: str, pr_body: str): pr_body=CodeCommitProvider._add_additional_newlines(pr_body), ) except Exception as e: - raise ValueError(f"CodeCommit Cannot publish description for PR: {self.pr_num}") from e + raise ValueError(f"CodeCommit Cannot publish description for PR: {self.pr_num}") from e def publish_comment(self, pr_comment: str, is_temporary: bool = False): if is_temporary: @@ -190,7 +192,7 @@ def publish_code_suggestions(self, code_suggestions: list) -> bool: if not all(key in suggestion for key in ["body", "relevant_file", "relevant_lines_start"]): get_logger().warning(f"Skipping code suggestion #{counter}: Each suggestion must have 'body', 'relevant_file', 'relevant_lines_start' keys") continue - + # Publish the code suggestion to CodeCommit try: get_logger().debug(f"Code Suggestion #{counter} in file: {suggestion['relevant_file']}: {suggestion['relevant_lines_start']}") @@ -205,12 +207,12 @@ def publish_code_suggestions(self, code_suggestions: list) -> bool: ) except Exception as e: raise ValueError(f"CodeCommit Cannot publish code suggestions for PR: {self.pr_num}") from e - + counter += 1 # The calling function passes in a list of code suggestions, and this function publishes each suggestion one at a time. # If we were to return False here, the calling function will attempt to publish the same list of code suggestions again, one at a time. - # Since this function publishes the suggestions one at a time anyway, we always return True here to avoid the retry. + # Since this function publishes the suggestions one at a time anyway, we always return True here to avoid the retry. return True def publish_labels(self, labels): @@ -238,7 +240,7 @@ def get_title(self): def get_pr_id(self): """ Returns the PR ID in the format: "repo_name/pr_number". - Note: This is an internal identifier for PR-Agent, + Note: This is an internal identifier for PR-Agent, and is not the same as the CodeCommit PR identifier. """ try: @@ -246,7 +248,7 @@ def get_pr_id(self): return pr_id except: return "" - + def get_languages(self): """ Returns a dictionary of languages, containing the percentage of each language used in the PR. @@ -348,7 +350,7 @@ def _is_valid_codecommit_hostname(hostname: str) -> bool: """ Check if the provided hostname is a valid AWS CodeCommit hostname. - This is not an exhaustive check of AWS region names, + This is not an exhaustive check of AWS region names, but instead uses a regex to check for matching AWS region patterns. Args: diff --git a/pr_agent/git_providers/gerrit_provider.py b/pr_agent/git_providers/gerrit_provider.py index 8ec1be135..ba5876563 100644 --- a/pr_agent/git_providers/gerrit_provider.py +++ b/pr_agent/git_providers/gerrit_provider.py @@ -12,9 +12,9 @@ import urllib3.util from git import Repo +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from pr_agent.config_loader import get_settings from pr_agent.git_providers.git_provider import GitProvider -from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from pr_agent.git_providers.local_git_provider import PullRequestMimic from pr_agent.log import get_logger diff --git a/pr_agent/git_providers/git_provider.py b/pr_agent/git_providers/git_provider.py index 265e54d9c..bc081aa49 100644 --- a/pr_agent/git_providers/git_provider.py +++ b/pr_agent/git_providers/git_provider.py @@ -1,12 +1,12 @@ from abc import ABC, abstractmethod - # enum EDIT_TYPE (ADDED, DELETED, MODIFIED, RENAMED) from typing import Optional +from pr_agent.algo.types import FilePatchInfo from pr_agent.algo.utils import Range, process_description from pr_agent.config_loader import get_settings -from pr_agent.algo.types import FilePatchInfo from pr_agent.log import get_logger + MAX_FILES_ALLOWED_FULL = 50 class GitProvider(ABC): @@ -62,8 +62,8 @@ def reply_to_comment_from_comment_id(self, comment_id: int, body: str): pass def get_pr_description(self, full: bool = True, split_changes_walkthrough=False) -> str or tuple: - from pr_agent.config_loader import get_settings from pr_agent.algo.utils import clip_tokens + from pr_agent.config_loader import get_settings max_tokens_description = get_settings().get("CONFIG.MAX_DESCRIPTION_TOKENS", None) description = self.get_pr_description_full() if full else self.get_user_description() if split_changes_walkthrough: diff --git a/pr_agent/git_providers/github_provider.py b/pr_agent/git_providers/github_provider.py index 61de7f268..4137ea48a 100644 --- a/pr_agent/git_providers/github_provider.py +++ b/pr_agent/git_providers/github_provider.py @@ -1,10 +1,11 @@ +import hashlib import itertools import time -import hashlib import traceback from datetime import datetime from typing import Optional, Tuple from urllib.parse import urlparse + from github import AppAuthentication, Auth, Github from retry import retry from starlette_context import context @@ -12,11 +13,14 @@ from ..algo.file_filter import filter_ignored from ..algo.language_handler import is_valid_file from ..algo.types import EDIT_TYPE -from ..algo.utils import PRReviewHeader, load_large_diff, clip_tokens, find_line_number_of_relevant_line_in_file, Range +from ..algo.utils import (PRReviewHeader, Range, clip_tokens, + find_line_number_of_relevant_line_in_file, + load_large_diff) from ..config_loader import get_settings from ..log import get_logger from ..servers.utils import RateLimitExceeded -from .git_provider import FilePatchInfo, GitProvider, IncrementalPR, MAX_FILES_ALLOWED_FULL +from .git_provider import (MAX_FILES_ALLOWED_FULL, FilePatchInfo, GitProvider, + IncrementalPR) class GithubProvider(GitProvider): diff --git a/pr_agent/git_providers/gitlab_provider.py b/pr_agent/git_providers/gitlab_provider.py index 443f41618..6a7b85c3d 100644 --- a/pr_agent/git_providers/gitlab_provider.py +++ b/pr_agent/git_providers/gitlab_provider.py @@ -7,13 +7,16 @@ import requests from gitlab import GitlabGetError +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo + from ..algo.file_filter import filter_ignored from ..algo.language_handler import is_valid_file -from ..algo.utils import load_large_diff, clip_tokens, find_line_number_of_relevant_line_in_file +from ..algo.utils import (clip_tokens, + find_line_number_of_relevant_line_in_file, + load_large_diff) from ..config_loader import get_settings -from .git_provider import GitProvider, MAX_FILES_ALLOWED_FULL -from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from ..log import get_logger +from .git_provider import MAX_FILES_ALLOWED_FULL, GitProvider class DiffNotFoundError(Exception): diff --git a/pr_agent/git_providers/local_git_provider.py b/pr_agent/git_providers/local_git_provider.py index c104224ac..a03b8ec23 100644 --- a/pr_agent/git_providers/local_git_provider.py +++ b/pr_agent/git_providers/local_git_provider.py @@ -4,9 +4,9 @@ from git import Repo +from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from pr_agent.config_loader import _find_repository_root, get_settings from pr_agent.git_providers.git_provider import GitProvider -from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from pr_agent.log import get_logger diff --git a/pr_agent/git_providers/utils.py b/pr_agent/git_providers/utils.py index 10beb1bb8..1f780ae93 100644 --- a/pr_agent/git_providers/utils.py +++ b/pr_agent/git_providers/utils.py @@ -3,11 +3,12 @@ import tempfile from dynaconf import Dynaconf +from starlette_context import context from pr_agent.config_loader import get_settings -from pr_agent.git_providers import get_git_provider, get_git_provider_with_context +from pr_agent.git_providers import (get_git_provider, + get_git_provider_with_context) from pr_agent.log import get_logger -from starlette_context import context def apply_repo_settings(pr_url): diff --git a/pr_agent/identity_providers/__init__.py b/pr_agent/identity_providers/__init__.py index 6df37ecb6..aa617ef44 100644 --- a/pr_agent/identity_providers/__init__.py +++ b/pr_agent/identity_providers/__init__.py @@ -1,5 +1,6 @@ from pr_agent.config_loader import get_settings -from pr_agent.identity_providers.default_identity_provider import DefaultIdentityProvider +from pr_agent.identity_providers.default_identity_provider import \ + DefaultIdentityProvider _IDENTITY_PROVIDERS = { 'default': DefaultIdentityProvider @@ -10,4 +11,4 @@ def get_identity_provider(): identity_provider_id = get_settings().get("CONFIG.IDENTITY_PROVIDER", "default") if identity_provider_id not in _IDENTITY_PROVIDERS: raise ValueError(f"Unknown identity provider: {identity_provider_id}") - return _IDENTITY_PROVIDERS[identity_provider_id]() \ No newline at end of file + return _IDENTITY_PROVIDERS[identity_provider_id]() diff --git a/pr_agent/identity_providers/default_identity_provider.py b/pr_agent/identity_providers/default_identity_provider.py index c542e1c28..341f6cb95 100644 --- a/pr_agent/identity_providers/default_identity_provider.py +++ b/pr_agent/identity_providers/default_identity_provider.py @@ -1,4 +1,5 @@ -from pr_agent.identity_providers.identity_provider import Eligibility, IdentityProvider +from pr_agent.identity_providers.identity_provider import (Eligibility, + IdentityProvider) class DefaultIdentityProvider(IdentityProvider): diff --git a/pr_agent/secret_providers/__init__.py b/pr_agent/secret_providers/__init__.py index 020ed16c4..c9faf4809 100644 --- a/pr_agent/secret_providers/__init__.py +++ b/pr_agent/secret_providers/__init__.py @@ -8,12 +8,10 @@ def get_secret_provider(): provider_id = get_settings().config.secret_provider if provider_id == 'google_cloud_storage': try: - from pr_agent.secret_providers.google_cloud_storage_secret_provider import GoogleCloudStorageSecretProvider + from pr_agent.secret_providers.google_cloud_storage_secret_provider import \ + GoogleCloudStorageSecretProvider return GoogleCloudStorageSecretProvider() except Exception as e: raise ValueError(f"Failed to initialize google_cloud_storage secret provider {provider_id}") from e else: raise ValueError("Unknown SECRET_PROVIDER") - - - diff --git a/pr_agent/servers/azuredevops_server_webhook.py b/pr_agent/servers/azuredevops_server_webhook.py index 37446659a..bcee3cdf0 100644 --- a/pr_agent/servers/azuredevops_server_webhook.py +++ b/pr_agent/servers/azuredevops_server_webhook.py @@ -9,9 +9,9 @@ from urllib.parse import unquote import uvicorn -from fastapi import APIRouter, Depends, FastAPI, HTTPException -from fastapi.security import HTTPBasic, HTTPBasicCredentials +from fastapi import APIRouter, Depends, FastAPI, HTTPException, Request from fastapi.encoders import jsonable_encoder +from fastapi.security import HTTPBasic, HTTPBasicCredentials from starlette import status from starlette.background import BackgroundTasks from starlette.middleware import Middleware @@ -23,9 +23,6 @@ from pr_agent.algo.utils import update_settings_from_args from pr_agent.config_loader import get_settings from pr_agent.git_providers.utils import apply_repo_settings -from pr_agent.log import get_logger -from fastapi import Request, Depends -from fastapi.security import HTTPBasic, HTTPBasicCredentials from pr_agent.log import LoggingFormat, get_logger, setup_logger setup_logger(fmt=LoggingFormat.JSON, level="DEBUG") diff --git a/pr_agent/servers/bitbucket_server_webhook.py b/pr_agent/servers/bitbucket_server_webhook.py index c9bfa5d9d..69167c333 100644 --- a/pr_agent/servers/bitbucket_server_webhook.py +++ b/pr_agent/servers/bitbucket_server_webhook.py @@ -6,20 +6,20 @@ import uvicorn from fastapi import APIRouter, FastAPI from fastapi.encoders import jsonable_encoder +from fastapi.responses import RedirectResponse from starlette import status from starlette.background import BackgroundTasks from starlette.middleware import Middleware from starlette.requests import Request from starlette.responses import JSONResponse from starlette_context.middleware import RawContextMiddleware + from pr_agent.agent.pr_agent import PRAgent from pr_agent.algo.utils import update_settings_from_args from pr_agent.config_loader import get_settings from pr_agent.git_providers.utils import apply_repo_settings from pr_agent.log import LoggingFormat, get_logger, setup_logger from pr_agent.servers.utils import verify_signature -from fastapi.responses import RedirectResponse - setup_logger(fmt=LoggingFormat.JSON, level="DEBUG") router = APIRouter() diff --git a/pr_agent/servers/github_app.py b/pr_agent/servers/github_app.py index 728d72c16..d0ac8d5a2 100644 --- a/pr_agent/servers/github_app.py +++ b/pr_agent/servers/github_app.py @@ -15,7 +15,8 @@ from pr_agent.agent.pr_agent import PRAgent from pr_agent.algo.utils import update_settings_from_args from pr_agent.config_loader import get_settings, global_settings -from pr_agent.git_providers import get_git_provider, get_git_provider_with_context +from pr_agent.git_providers import (get_git_provider, + get_git_provider_with_context) from pr_agent.git_providers.git_provider import IncrementalPR from pr_agent.git_providers.utils import apply_repo_settings from pr_agent.identity_providers import get_identity_provider diff --git a/pr_agent/servers/github_polling.py b/pr_agent/servers/github_polling.py index de1a9f529..5eab94dc4 100644 --- a/pr_agent/servers/github_polling.py +++ b/pr_agent/servers/github_polling.py @@ -1,11 +1,12 @@ import asyncio import multiprocessing -from collections import deque +import time import traceback +from collections import deque from datetime import datetime, timezone -import time -import requests + import aiohttp +import requests from pr_agent.agent.pr_agent import PRAgent from pr_agent.config_loader import get_settings diff --git a/pr_agent/servers/gitlab_webhook.py b/pr_agent/servers/gitlab_webhook.py index e3e80dfae..b5a50ebe7 100644 --- a/pr_agent/servers/gitlab_webhook.py +++ b/pr_agent/servers/gitlab_webhook.py @@ -1,6 +1,6 @@ import copy -import re import json +import re from datetime import datetime import uvicorn diff --git a/pr_agent/servers/help.py b/pr_agent/servers/help.py index 5578fb0f5..7edd13db5 100644 --- a/pr_agent/servers/help.py +++ b/pr_agent/servers/help.py @@ -82,7 +82,7 @@ def get_describe_usage_guide(): - `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. - + """ output += "\n\n\n\n" @@ -101,7 +101,7 @@ def get_describe_usage_guide(): 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. -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. +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. """ output += "\n\n\n\n" @@ -126,7 +126,7 @@ def get_describe_usage_guide(): Examples for extra instructions: ``` -[pr_description] +[pr_description] extra_instructions="""\ - The PR title should be in the format: ': ' - The title should be short and concise (up to 10 words) @@ -159,8 +159,8 @@ def get_ask_usage_guide(): /ask "..." ``` -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. +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>" # @@ -195,9 +195,9 @@ def get_improve_usage_guide(): some_config1=... some_config2=... ``` - + """ output += f"\n\nSee the improve [usage page](https://pr-agent-docs.codium.ai/tools/improve/) for a comprehensive guide on using this tool.\n\n" - return output \ No newline at end of file + return output diff --git a/pr_agent/servers/serverless.py b/pr_agent/servers/serverless.py index c0bce6067..a46eb80ac 100644 --- a/pr_agent/servers/serverless.py +++ b/pr_agent/servers/serverless.py @@ -5,7 +5,6 @@ from pr_agent.servers.github_app import router - middleware = [Middleware(RawContextMiddleware)] app = FastAPI(middleware=middleware) app.include_router(router) diff --git a/pr_agent/servers/utils.py b/pr_agent/servers/utils.py index 12dd85ae8..4b1ea80b3 100644 --- a/pr_agent/servers/utils.py +++ b/pr_agent/servers/utils.py @@ -2,7 +2,7 @@ import hmac import time from collections import defaultdict -from typing import Callable, Any +from typing import Any, Callable from fastapi import HTTPException diff --git a/pr_agent/settings/.secrets_template.toml b/pr_agent/settings/.secrets_template.toml index 6da82327f..bb3ee4590 100644 --- a/pr_agent/settings/.secrets_template.toml +++ b/pr_agent/settings/.secrets_template.toml @@ -87,7 +87,7 @@ org = "" pat = "" [azure_devops_server] -# For Azure devops Server basic auth - configured in the webhook creation +# For Azure devops Server basic auth - configured in the webhook creation # Optional, uncomment if you want to use Azure devops webhooks. Value assinged when you create the webhook # webhook_username = "<basic auth user>" # webhook_password = "<basic auth password>" diff --git a/pr_agent/settings/custom_labels.toml b/pr_agent/settings/custom_labels.toml index ee45fb198..34d604b5f 100644 --- a/pr_agent/settings/custom_labels.toml +++ b/pr_agent/settings/custom_labels.toml @@ -13,4 +13,4 @@ enable_custom_labels=false #[custom_labels."Documentation"] #description = """Adds or modifies documentation""" #[custom_labels."Other"] -#description = """Other changes that do not fit in any of the above categories""" \ No newline at end of file +#description = """Other changes that do not fit in any of the above categories""" diff --git a/pr_agent/settings/language_extensions.toml b/pr_agent/settings/language_extensions.toml index 2f3e5542b..0cc6c700f 100644 --- a/pr_agent/settings/language_extensions.toml +++ b/pr_agent/settings/language_extensions.toml @@ -437,4 +437,4 @@ xBase = [".prg", ".prw", ] [docs_blacklist_extensions] # Disable docs for these extensions of text files and scripts that are not programming languages of function, classes and methods -docs_blacklist = ['sql', 'txt', 'yaml', 'json', 'xml', 'md', 'rst', 'rest', 'rest.txt', 'rst.txt', 'mdpolicy', 'mdown', 'markdown', 'mdwn', 'mkd', 'mkdn', 'mkdown', 'sh'] \ No newline at end of file +docs_blacklist = ['sql', 'txt', 'yaml', 'json', 'xml', 'md', 'rst', 'rest', 'rest.txt', 'rst.txt', 'mdpolicy', 'mdown', 'markdown', 'mdwn', 'mkd', 'mkdn', 'mkdown', 'sh'] diff --git a/pr_agent/settings/pr_code_suggestions_prompts.toml b/pr_agent/settings/pr_code_suggestions_prompts.toml index 5bf15f595..be47b3ce8 100644 --- a/pr_agent/settings/pr_code_suggestions_prompts.toml +++ b/pr_agent/settings/pr_code_suggestions_prompts.toml @@ -118,4 +118,4 @@ The PR Diff: Response (should be a valid YAML, and nothing else): ```yaml -""" \ No newline at end of file +""" diff --git a/pr_agent/tools/pr_code_suggestions.py b/pr_agent/tools/pr_code_suggestions.py index 1426ff1a7..ae3efbb21 100644 --- a/pr_agent/tools/pr_code_suggestions.py +++ b/pr_agent/tools/pr_code_suggestions.py @@ -1,25 +1,29 @@ import asyncio import copy +import difflib +import re import textwrap from functools import partial from typing import Dict, List + from jinja2 import Environment, StrictUndefined from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler -from pr_agent.algo.pr_processing import get_pr_diff, get_pr_multi_diffs, retry_with_fallback_models, \ - add_ai_metadata_to_diff_files +from pr_agent.algo.pr_processing import (add_ai_metadata_to_diff_files, + get_pr_diff, get_pr_multi_diffs, + retry_with_fallback_models) from pr_agent.algo.token_handler import TokenHandler -from pr_agent.algo.utils import load_yaml, replace_code_tags, ModelType, show_relevant_configurations +from pr_agent.algo.utils import (ModelType, load_yaml, replace_code_tags, + show_relevant_configurations) from pr_agent.config_loader import get_settings -from pr_agent.git_providers import get_git_provider, get_git_provider_with_context, GithubProvider, GitLabProvider, \ - AzureDevopsProvider +from pr_agent.git_providers import (AzureDevopsProvider, GithubProvider, + GitLabProvider, get_git_provider, + get_git_provider_with_context) from pr_agent.git_providers.git_provider import get_main_pr_language from pr_agent.log import get_logger from pr_agent.servers.help import HelpMessage from pr_agent.tools.pr_description import insert_br_after_x_chars -import difflib -import re class PRCodeSuggestions: @@ -726,7 +730,7 @@ def generate_summarized_suggestions(self, data: Dict) -> str: [{relevant_file} {range_str}]({code_snippet_link}) -{example_code.rstrip()} +{example_code.rstrip()} """ if get_settings().pr_code_suggestions.self_reflect_on_suggestions: pr_body += f"<details><summary>Suggestion importance[1-10]: {suggestion['score']}</summary>\n\n" @@ -778,4 +782,3 @@ async def self_reflect_on_suggestions(self, suggestion_list: List, patches_diff: get_logger().info(f"Could not reflect on suggestions, error: {e}") return "" return response_reflect - diff --git a/pr_agent/tools/pr_description.py b/pr_agent/tools/pr_description.py index 1d397a540..2c3610d79 100644 --- a/pr_agent/tools/pr_description.py +++ b/pr_agent/tools/pr_description.py @@ -9,19 +9,24 @@ from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler -from pr_agent.algo.pr_processing import get_pr_diff, retry_with_fallback_models, get_pr_diff_multiple_patchs, \ - OUTPUT_BUFFER_TOKENS_HARD_THRESHOLD +from pr_agent.algo.pr_processing import (OUTPUT_BUFFER_TOKENS_HARD_THRESHOLD, + get_pr_diff, + get_pr_diff_multiple_patchs, + retry_with_fallback_models) from pr_agent.algo.token_handler import TokenHandler -from pr_agent.algo.utils import set_custom_labels, PRDescriptionHeader -from pr_agent.algo.utils import load_yaml, get_user_labels, ModelType, show_relevant_configurations, get_max_tokens, \ - clip_tokens +from pr_agent.algo.utils import (ModelType, PRDescriptionHeader, clip_tokens, + get_max_tokens, get_user_labels, load_yaml, + set_custom_labels, + show_relevant_configurations) from pr_agent.config_loader import get_settings -from pr_agent.git_providers import get_git_provider, GithubProvider, get_git_provider_with_context +from pr_agent.git_providers import (GithubProvider, get_git_provider, + get_git_provider_with_context) from pr_agent.git_providers.git_provider import get_main_pr_language from pr_agent.log import get_logger from pr_agent.servers.help import HelpMessage -from pr_agent.tools.ticket_pr_compliance_check import extract_ticket_links_from_pr_description, extract_tickets, \ - extract_and_cache_pr_tickets +from pr_agent.tools.ticket_pr_compliance_check import ( + extract_and_cache_pr_tickets, extract_ticket_links_from_pr_description, + extract_tickets) class PRDescription: @@ -297,7 +302,7 @@ async def _prepare_prediction(self, model: str) -> None: files_walkthrough = files_walkthrough.strip() + "\n" + extra_file_yaml.strip() if i >= MAX_EXTRA_FILES_TO_OUTPUT: files_walkthrough += f"""\ -extra_file_yaml = +extra_file_yaml = - filename: | Additional {len(remaining_files_list) - MAX_EXTRA_FILES_TO_OUTPUT} files not shown changes_summary: | @@ -611,7 +616,7 @@ def process_pr_files_prediction(self, pr_body, value): </td> <td><a href="{link}">{diff_plus_minus}</a>{delta_nbsp}</td> -</tr> +</tr> """ if use_collapsible_file_list: pr_body += """</table></details></td></tr>""" diff --git a/pr_agent/tools/pr_generate_labels.py b/pr_agent/tools/pr_generate_labels.py index 1911e0cd9..dae25d914 100644 --- a/pr_agent/tools/pr_generate_labels.py +++ b/pr_agent/tools/pr_generate_labels.py @@ -9,7 +9,7 @@ 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.token_handler import TokenHandler -from pr_agent.algo.utils import load_yaml, set_custom_labels, get_user_labels +from pr_agent.algo.utils import get_user_labels, load_yaml, set_custom_labels from pr_agent.config_loader import get_settings from pr_agent.git_providers import get_git_provider from pr_agent.git_providers.git_provider import get_main_pr_language @@ -57,7 +57,7 @@ def __init__(self, pr_url: str, args: list = None, get_settings().pr_custom_labels_prompt.system, get_settings().pr_custom_labels_prompt.user, ) - + # Initialize patches_diff and prediction attributes self.patches_diff = None self.prediction = None @@ -98,7 +98,7 @@ async def run(self): self.git_provider.remove_initial_comment() except Exception as e: get_logger().error(f"Error generating PR labels {self.pr_id}: {e}") - + return "" async def _prepare_prediction(self, model: str) -> None: diff --git a/pr_agent/tools/pr_help_message.py b/pr_agent/tools/pr_help_message.py index 09845f814..3b0ed5a18 100644 --- a/pr_agent/tools/pr_help_message.py +++ b/pr_agent/tools/pr_help_message.py @@ -9,10 +9,10 @@ from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler from pr_agent.algo.pr_processing import retry_with_fallback_models from pr_agent.algo.token_handler import TokenHandler -from pr_agent.algo.utils import ModelType, load_yaml, clip_tokens +from pr_agent.algo.utils import ModelType, clip_tokens, load_yaml from pr_agent.config_loader import get_settings -from pr_agent.git_providers import GithubProvider, BitbucketServerProvider, \ - get_git_provider_with_context +from pr_agent.git_providers import (BitbucketServerProvider, GithubProvider, + get_git_provider_with_context) from pr_agent.log import get_logger diff --git a/pr_agent/tools/pr_line_questions.py b/pr_agent/tools/pr_line_questions.py index 56818e1cd..50bf41838 100644 --- a/pr_agent/tools/pr_line_questions.py +++ b/pr_agent/tools/pr_line_questions.py @@ -6,8 +6,8 @@ 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.git_patch_processing import convert_to_hunks_with_lines_numbers, \ - extract_hunk_lines_from_patch +from pr_agent.algo.git_patch_processing import ( + convert_to_hunks_with_lines_numbers, extract_hunk_lines_from_patch) 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.utils import ModelType diff --git a/pr_agent/tools/pr_reviewer.py b/pr_agent/tools/pr_reviewer.py index f5f82e060..e008703e6 100644 --- a/pr_agent/tools/pr_reviewer.py +++ b/pr_agent/tools/pr_reviewer.py @@ -4,19 +4,27 @@ from collections import OrderedDict from functools import partial from typing import List, Tuple + from jinja2 import Environment, StrictUndefined + from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler -from pr_agent.algo.pr_processing import get_pr_diff, retry_with_fallback_models, add_ai_metadata_to_diff_files +from pr_agent.algo.pr_processing import (add_ai_metadata_to_diff_files, + get_pr_diff, + retry_with_fallback_models) from pr_agent.algo.token_handler import TokenHandler -from pr_agent.algo.utils import github_action_output, load_yaml, ModelType, \ - show_relevant_configurations, convert_to_markdown_v2, PRReviewHeader +from pr_agent.algo.utils import (ModelType, PRReviewHeader, + convert_to_markdown_v2, github_action_output, + load_yaml, show_relevant_configurations) from pr_agent.config_loader import get_settings -from pr_agent.git_providers import get_git_provider, get_git_provider_with_context -from pr_agent.git_providers.git_provider import IncrementalPR, get_main_pr_language +from pr_agent.git_providers import (get_git_provider, + get_git_provider_with_context) +from pr_agent.git_providers.git_provider import (IncrementalPR, + get_main_pr_language) from pr_agent.log import get_logger from pr_agent.servers.help import HelpMessage -from pr_agent.tools.ticket_pr_compliance_check import extract_tickets, extract_and_cache_pr_tickets +from pr_agent.tools.ticket_pr_compliance_check import ( + extract_and_cache_pr_tickets, extract_tickets) class PRReviewer: diff --git a/pr_agent/tools/pr_similar_issue.py b/pr_agent/tools/pr_similar_issue.py index 1a4d794ab..dfa34c527 100644 --- a/pr_agent/tools/pr_similar_issue.py +++ b/pr_agent/tools/pr_similar_issue.py @@ -34,9 +34,9 @@ def __init__(self, issue_url: str, ai_handler, args: list = None): if get_settings().pr_similar_issue.vectordb == "pinecone": try: + import pandas as pd import pinecone from pinecone_datasets import Dataset, DatasetMetadata - import pandas as pd except: raise Exception("Please install 'pinecone' and 'pinecone_datasets' to use pinecone as vectordb") # assuming pinecone api key and environment are set in secrets file @@ -108,10 +108,10 @@ def __init__(self, issue_url: str, ai_handler, args: list = None): self._update_index_with_issues(issues_to_update, repo_name_for_index, upsert=True) else: get_logger().info('No new issues to update') - + elif get_settings().pr_similar_issue.vectordb == "lancedb": try: - import lancedb # import lancedb only if needed + import lancedb # import lancedb only if needed except: raise Exception("Please install lancedb to use lancedb as vectordb") self.db = lancedb.connect(get_settings().lancedb.uri) @@ -173,7 +173,7 @@ def __init__(self, issue_url: str, ai_handler, args: list = None): self._update_table_with_issues(issues_to_update, repo_name_for_index, ingest=True) else: get_logger().info('No new issues to update') - + async def run(self): get_logger().info('Getting issue...') @@ -190,14 +190,14 @@ async def run(self): relevant_issues_number_list = [] relevant_comment_number_list = [] score_list = [] - + if get_settings().pr_similar_issue.vectordb == "pinecone": pinecone_index = pinecone.Index(index_name=self.index_name) res = pinecone_index.query(embeds[0], top_k=5, filter={"repo": self.repo_name_for_index}, include_metadata=True).to_dict() - + for r in res['matches']: # skip example issue if 'example_issue_' in r["id"]: @@ -222,12 +222,12 @@ async def run(self): elif get_settings().pr_similar_issue.vectordb == "lancedb": res = self.table.search(embeds[0]).where(f"metadata.repo='{self.repo_name_for_index}'", prefilter=True).to_list() - + for r in res: # skip example issue if 'example_issue_' in r["id"]: continue - + try: issue_number = int(r["id"].split('.')[0].split('_')[-1]) except: @@ -238,14 +238,14 @@ async def run(self): continue if issue_number not in relevant_issues_number_list: relevant_issues_number_list.append(issue_number) - + if 'comment' in r["id"]: relevant_comment_number_list.append(int(r["id"].split('.')[1].split('_')[-1])) else: relevant_comment_number_list.append(-1) score_list.append(str("{:.2f}".format(1-r['_distance']))) get_logger().info('Done') - + get_logger().info('Publishing response...') similar_issues_str = "### Similar Issues\n___\n\n" @@ -447,14 +447,14 @@ def _update_table_with_issues(self, issues_list, repo_name_for_index, ingest=Fal if not ingest: get_logger().info('Creating table from scratch...') self.table = self.db.create_table(self.index_name, data=df, mode="overwrite") - time.sleep(15) + time.sleep(15) else: get_logger().info('Ingesting in Table...') if self.index_name not in self.db.table_names(): self.table.add(df) else: get_logger().info(f"Table {self.index_name} doesn't exists!") - time.sleep(5) + time.sleep(5) get_logger().info('Done') diff --git a/pr_agent/tools/pr_update_changelog.py b/pr_agent/tools/pr_update_changelog.py index dfe90a0df..521364309 100644 --- a/pr_agent/tools/pr_update_changelog.py +++ b/pr_agent/tools/pr_update_changelog.py @@ -3,14 +3,16 @@ from functools import partial from time import sleep from typing import Tuple + from jinja2 import Environment, StrictUndefined + from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler from pr_agent.algo.pr_processing import get_pr_diff, retry_with_fallback_models from pr_agent.algo.token_handler import TokenHandler from pr_agent.algo.utils import ModelType, show_relevant_configurations from pr_agent.config_loader import get_settings -from pr_agent.git_providers import get_git_provider, GithubProvider +from pr_agent.git_providers import GithubProvider, get_git_provider from pr_agent.git_providers.git_provider import get_main_pr_language from pr_agent.log import get_logger diff --git a/pyproject.toml b/pyproject.toml index 86ce9a32a..cc4264288 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,19 +6,19 @@ build-backend = "setuptools.build_meta" name = "pr-agent" version = "0.2.4" -authors = [{name= "CodiumAI", email = "tal.r@codium.ai"}] +authors = [{ name = "CodiumAI", email = "tal.r@codium.ai" }] maintainers = [ - {name = "Tal Ridnik", email = "tal.r@codium.ai"}, - {name = "Ori Kotek", email = "ori.k@codium.ai"}, - {name = "Hussam Lawen", email = "hussam.l@codium.ai"}, + { name = "Tal Ridnik", email = "tal.r@codium.ai" }, + { name = "Ori Kotek", email = "ori.k@codium.ai" }, + { name = "Hussam Lawen", email = "hussam.l@codium.ai" }, ] description = "CodiumAI PR-Agent aims to help efficiently review and handle pull requests, by providing AI feedbacks and suggestions." readme = "README.md" requires-python = ">=3.10" keywords = ["AI", "Agents", "Pull Request", "Automation", "Code Review"] -license = {name = "Apache 2.0", file = "LICENSE"} +license = { name = "Apache 2.0", file = "LICENSE" } classifiers = [ "Intended Audience :: Developers", @@ -28,7 +28,7 @@ dynamic = ["dependencies"] [tool.setuptools.dynamic] -dependencies = {file = ["requirements.txt"]} +dependencies = { file = ["requirements.txt"] } [project.urls] "Homepage" = "https://github.com/Codium-ai/pr-agent" @@ -40,41 +40,43 @@ license-files = ["LICENSE"] [tool.setuptools.packages.find] where = ["."] -include = ["pr_agent*"] # include pr_agent and any sub-packages it finds under it. +include = [ + "pr_agent*", +] # include pr_agent and any sub-packages it finds under it. [project.scripts] pr-agent = "pr_agent.cli:run" - [tool.ruff] - line-length = 120 -select = [ - "E", # Pyflakes - "F", # Pyflakes - "B", # flake8-bugbear - "I001", # isort basic checks - "I002", # isort missing-required-import - ] +lint.select = [ + "E", # Pyflakes + "F", # Pyflakes + "B", # flake8-bugbear + "I001", # isort basic checks + "I002", # isort missing-required-import +] # First commit - only fixing isort -fixable = [ - "I001", # isort basic checks +lint.fixable = [ + "I001", # isort basic checks ] -unfixable = [ - "B", # Avoid trying to fix flake8-bugbear (`B`) violations. - ] - -exclude = [ - "api/code_completions", +lint.unfixable = [ + "B", # Avoid trying to fix flake8-bugbear (`B`) violations. ] -ignore = [ - "E999", "B008" -] +lint.exclude = ["api/code_completions"] + +lint.ignore = ["E999", "B008"] + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = [ + "E402", +] # Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`. -[tool.ruff.per-file-ignores] -"__init__.py" = ["E402"] # Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`. -# TODO: should decide if maybe not to ignore these. +[tool.bandit] +exclude_dirs = ["tests"] +skips = ["B101"] +tests = [] diff --git a/tests/e2e_tests/e2e_utils.py b/tests/e2e_tests/e2e_utils.py index 5251d83e4..b39e2a463 100644 --- a/tests/e2e_tests/e2e_utils.py +++ b/tests/e2e_tests/e2e_utils.py @@ -32,4 +32,3 @@ def main(): if __name__ == '__main__': main() """ - diff --git a/tests/e2e_tests/test_bitbucket_app.py b/tests/e2e_tests/test_bitbucket_app.py index 47b9ca4f1..eb819eb27 100644 --- a/tests/e2e_tests/test_bitbucket_app.py +++ b/tests/e2e_tests/test_bitbucket_app.py @@ -5,16 +5,16 @@ from datetime import datetime import jwt -from atlassian.bitbucket import Cloud - import requests +from atlassian.bitbucket import Cloud from requests.auth import HTTPBasicAuth from pr_agent.config_loader import get_settings -from pr_agent.log import setup_logger, get_logger -from tests.e2e_tests.e2e_utils import NEW_FILE_CONTENT, FILE_PATH, PR_HEADER_START_WITH, REVIEW_START_WITH, \ - IMPROVE_START_WITH_REGEX_PATTERN, NUM_MINUTES - +from pr_agent.log import get_logger, setup_logger +from tests.e2e_tests.e2e_utils import (FILE_PATH, + IMPROVE_START_WITH_REGEX_PATTERN, + NEW_FILE_CONTENT, NUM_MINUTES, + PR_HEADER_START_WITH, REVIEW_START_WITH) log_level = os.environ.get("LOG_LEVEL", "INFO") setup_logger(log_level) diff --git a/tests/e2e_tests/test_github_app.py b/tests/e2e_tests/test_github_app.py index 6ecb1da8d..70b742a68 100644 --- a/tests/e2e_tests/test_github_app.py +++ b/tests/e2e_tests/test_github_app.py @@ -5,9 +5,11 @@ from pr_agent.config_loader import get_settings from pr_agent.git_providers import get_git_provider -from pr_agent.log import setup_logger, get_logger -from tests.e2e_tests.e2e_utils import NEW_FILE_CONTENT, FILE_PATH, PR_HEADER_START_WITH, REVIEW_START_WITH, \ - IMPROVE_START_WITH_REGEX_PATTERN, NUM_MINUTES +from pr_agent.log import get_logger, setup_logger +from tests.e2e_tests.e2e_utils import (FILE_PATH, + IMPROVE_START_WITH_REGEX_PATTERN, + NEW_FILE_CONTENT, NUM_MINUTES, + PR_HEADER_START_WITH, REVIEW_START_WITH) log_level = os.environ.get("LOG_LEVEL", "INFO") setup_logger(log_level) diff --git a/tests/e2e_tests/test_gitlab_webhook.py b/tests/e2e_tests/test_gitlab_webhook.py index 053bb0dc2..835a6d12b 100644 --- a/tests/e2e_tests/test_gitlab_webhook.py +++ b/tests/e2e_tests/test_gitlab_webhook.py @@ -7,9 +7,11 @@ from pr_agent.config_loader import get_settings from pr_agent.git_providers import get_git_provider -from pr_agent.log import setup_logger, get_logger -from tests.e2e_tests.e2e_utils import NEW_FILE_CONTENT, FILE_PATH, PR_HEADER_START_WITH, REVIEW_START_WITH, \ - IMPROVE_START_WITH_REGEX_PATTERN, NUM_MINUTES +from pr_agent.log import get_logger, setup_logger +from tests.e2e_tests.e2e_utils import (FILE_PATH, + IMPROVE_START_WITH_REGEX_PATTERN, + NEW_FILE_CONTENT, NUM_MINUTES, + PR_HEADER_START_WITH, REVIEW_START_WITH) log_level = os.environ.get("LOG_LEVEL", "INFO") setup_logger(log_level) diff --git a/tests/unittest/test_azure_devops_parsing.py b/tests/unittest/test_azure_devops_parsing.py index 84c0ad08c..441d4e356 100644 --- a/tests/unittest/test_azure_devops_parsing.py +++ b/tests/unittest/test_azure_devops_parsing.py @@ -12,4 +12,4 @@ def test_visualstudio_address(self): pr_url = "https://organization.visualstudio.com/project/_git/repo/pullrequest/1" # workspace_slug, repo_slug, pr_number - assert AzureDevopsProvider._parse_pr_url(pr_url) == ("project", "repo", 1) \ No newline at end of file + assert AzureDevopsProvider._parse_pr_url(pr_url) == ("project", "repo", 1) diff --git a/tests/unittest/test_bitbucket_provider.py b/tests/unittest/test_bitbucket_provider.py index 1ea99931c..5c6729289 100644 --- a/tests/unittest/test_bitbucket_provider.py +++ b/tests/unittest/test_bitbucket_provider.py @@ -1,8 +1,10 @@ -from pr_agent.git_providers import BitbucketServerProvider -from pr_agent.git_providers.bitbucket_provider import BitbucketProvider from unittest.mock import MagicMock + from atlassian.bitbucket import Bitbucket + from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo +from pr_agent.git_providers import BitbucketServerProvider +from pr_agent.git_providers.bitbucket_provider import BitbucketProvider class TestBitbucketProvider: @@ -121,7 +123,7 @@ def test_get_diff_files_simple_diverge_70(self): NOT between the HEAD of main and the HEAD of branch b - o - o - o branch b - / / + / / o - o -- o - o main ^ node c ''' @@ -183,7 +185,7 @@ def test_get_diff_files_diverge_with_merge_commit_70(self): ---- o - o branch c / / ---- o branch b - / / + / / o - o - o main ^ node d ''' @@ -294,4 +296,4 @@ def test_get_diff_files_multi_merge_diverge_816(self): actual = provider.get_diff_files() - assert actual == expected \ No newline at end of file + assert actual == expected diff --git a/tests/unittest/test_codecommit_client.py b/tests/unittest/test_codecommit_client.py index a81e4b326..f5d89c6cf 100644 --- a/tests/unittest/test_codecommit_client.py +++ b/tests/unittest/test_codecommit_client.py @@ -1,4 +1,5 @@ from unittest.mock import MagicMock + from pr_agent.git_providers.codecommit_client import CodeCommitClient diff --git a/tests/unittest/test_codecommit_provider.py b/tests/unittest/test_codecommit_provider.py index 56312d732..d080b50fe 100644 --- a/tests/unittest/test_codecommit_provider.py +++ b/tests/unittest/test_codecommit_provider.py @@ -1,9 +1,11 @@ -import pytest from unittest.mock import patch -from pr_agent.git_providers.codecommit_provider import CodeCommitFile -from pr_agent.git_providers.codecommit_provider import CodeCommitProvider -from pr_agent.git_providers.codecommit_provider import PullRequestCCMimic + +import pytest + from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo +from pr_agent.git_providers.codecommit_provider import (CodeCommitFile, + CodeCommitProvider, + PullRequestCCMimic) class TestCodeCommitFile: diff --git a/tests/unittest/test_convert_to_markdown.py b/tests/unittest/test_convert_to_markdown.py index 8b82677ad..4d1d1aa40 100644 --- a/tests/unittest/test_convert_to_markdown.py +++ b/tests/unittest/test_convert_to_markdown.py @@ -6,8 +6,8 @@ Code Analysis Objective: -The objective of the 'convert_to_markdown' function is to convert a dictionary of data into a markdown-formatted text. -The function takes in a dictionary as input and recursively iterates through its keys and values to generate the +The objective of the 'convert_to_markdown' function is to convert a dictionary of data into a markdown-formatted text. +The function takes in a dictionary as input and recursively iterates through its keys and values to generate the markdown text. Inputs: @@ -18,17 +18,17 @@ - Create a dictionary 'emojis' containing emojis for each key in the input dictionary. - Iterate through the input dictionary: - If the value is empty, continue to the next iteration. - - If the value is a dictionary, recursively call the 'convert_to_markdown' function with the value as input and + - If the value is a dictionary, recursively call the 'convert_to_markdown' function with the value as input and append the returned markdown text to 'markdown_text'. - If the value is a list: - If the key is 'code suggestions', add an additional line break to 'markdown_text'. - Get the corresponding emoji for the key from the 'emojis' dictionary. If no emoji is found, use a dash. - Append the emoji and key to 'markdown_text'. - Iterate through the items in the list: - - If the item is a dictionary and the key is 'code suggestions', call the 'parse_code_suggestion' function with + - If the item is a dictionary and the key is 'code suggestions', call the 'parse_code_suggestion' function with the item as input and append the returned markdown text to 'markdown_text'. - If the item is not empty, append it to 'markdown_text'. - - If the value is not 'n/a', get the corresponding emoji for the key from the 'emojis' dictionary. If no emoji is + - If the value is not 'n/a', get the corresponding emoji for the key from the 'emojis' dictionary. If no emoji is found, use a dash. Append the emoji, key, and value to 'markdown_text'. - Return 'markdown_text'. diff --git a/tests/unittest/test_delete_hunks.py b/tests/unittest/test_delete_hunks.py index 20b9a6763..78ecc9478 100644 --- a/tests/unittest/test_delete_hunks.py +++ b/tests/unittest/test_delete_hunks.py @@ -6,7 +6,7 @@ Code Analysis Objective: -The objective of the "omit_deletion_hunks" function is to remove deletion hunks from a patch file and return only the +The objective of the "omit_deletion_hunks" function is to remove deletion hunks from a patch file and return only the added lines. Inputs: @@ -16,11 +16,11 @@ - Initialize empty lists "temp_hunk" and "added_patched", and boolean variables "add_hunk" and "inside_hunk". - Compile a regular expression pattern to match hunk headers. - Iterate through each line in "patch_lines". -- If the line starts with "@@", match the line with the hunk header pattern, finish the previous hunk if necessary, +- If the line starts with "@@", match the line with the hunk header pattern, finish the previous hunk if necessary, and append the line to "temp_hunk". -- If the line does not start with "@@", append the line to "temp_hunk", check if it is an added line, and set +- If the line does not start with "@@", append the line to "temp_hunk", check if it is an added line, and set "add_hunk" to True if it is. -- If the function reaches the end of "patch_lines" and there is an unfinished hunk with added lines, append it to +- If the function reaches the end of "patch_lines" and there is an unfinished hunk with added lines, append it to "added_patched". - Join the lines in "added_patched" with newline characters and return the resulting string. diff --git a/tests/unittest/test_extend_patch.py b/tests/unittest/test_extend_patch.py index 2d8913f39..6689186c9 100644 --- a/tests/unittest/test_extend_patch.py +++ b/tests/unittest/test_extend_patch.py @@ -1,4 +1,5 @@ import pytest + from pr_agent.algo.git_patch_processing import extend_patch from pr_agent.algo.pr_processing import pr_generate_extended_diff from pr_agent.algo.token_handler import TokenHandler diff --git a/tests/unittest/test_file_filter.py b/tests/unittest/test_file_filter.py index 43e9c9b4f..b35e351f6 100644 --- a/tests/unittest/test_file_filter.py +++ b/tests/unittest/test_file_filter.py @@ -1,7 +1,9 @@ import pytest + from pr_agent.algo.file_filter import filter_ignored from pr_agent.config_loader import global_settings + class TestIgnoreFilter: def test_no_ignores(self): """ diff --git a/tests/unittest/test_find_line_number_of_relevant_line_in_file.py b/tests/unittest/test_find_line_number_of_relevant_line_in_file.py index fcb028cae..07be17f46 100644 --- a/tests/unittest/test_find_line_number_of_relevant_line_in_file.py +++ b/tests/unittest/test_find_line_number_of_relevant_line_in_file.py @@ -1,9 +1,10 @@ # Generated by CodiumAI +import pytest + from pr_agent.algo.types import FilePatchInfo from pr_agent.algo.utils import find_line_number_of_relevant_line_in_file -import pytest class TestFindLineNumberOfRelevantLineInFile: # Tests that the function returns the correct line number and absolute position when the relevant line is found in the patch @@ -64,4 +65,4 @@ def test_relevant_line_found_but_deleted(self): relevant_file = 'file1' relevant_line_in_file = 'relevant_line' expected = (-1, -1) - assert find_line_number_of_relevant_line_in_file(diff_files, relevant_file, relevant_line_in_file) == expected \ No newline at end of file + assert find_line_number_of_relevant_line_in_file(diff_files, relevant_file, relevant_line_in_file) == expected diff --git a/tests/unittest/test_github_action_output.py b/tests/unittest/test_github_action_output.py index 2b8e0db19..57a62c6ea 100644 --- a/tests/unittest/test_github_action_output.py +++ b/tests/unittest/test_github_action_output.py @@ -1,33 +1,35 @@ -import os import json +import os + 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): @@ -35,16 +37,16 @@ def test_github_action_output_notset(self, monkeypatch, tmp_path): 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')) \ No newline at end of file + + assert not os.path.exists(str(tmp_path / 'output')) diff --git a/tests/unittest/test_handle_patch_deletions.py b/tests/unittest/test_handle_patch_deletions.py index e44c0d771..c216f189d 100644 --- a/tests/unittest/test_handle_patch_deletions.py +++ b/tests/unittest/test_handle_patch_deletions.py @@ -8,7 +8,7 @@ Code Analysis Objective: -The objective of the function is to handle entire file or deletion patches and return the patch after omitting the +The objective of the function is to handle entire file or deletion patches and return the patch after omitting the deletion hunks. Inputs: diff --git a/tests/unittest/test_language_handler.py b/tests/unittest/test_language_handler.py index fdde7bb03..f76a15ea3 100644 --- a/tests/unittest/test_language_handler.py +++ b/tests/unittest/test_language_handler.py @@ -7,8 +7,8 @@ Code Analysis Objective: -The objective of the function is to sort a list of files by their main language, putting the files that are in the main -language first and the rest of the files after. It takes in a dictionary of languages and their sizes, and a list of +The objective of the function is to sort a list of files by their main language, putting the files that are in the main +language first and the rest of the files after. It takes in a dictionary of languages and their sizes, and a list of files. Inputs: diff --git a/tests/unittest/test_load_yaml.py b/tests/unittest/test_load_yaml.py index 17d469360..5be0b1a2a 100644 --- a/tests/unittest/test_load_yaml.py +++ b/tests/unittest/test_load_yaml.py @@ -47,7 +47,3 @@ def test_load_invalid_yaml2(self): expected_output = [{'relevant file': 'src/app.py:\n', 'suggestion content': 'The print statement is outside inside the if __name__ ==:'}] assert load_yaml(yaml_str) == expected_output - - - - diff --git a/tests/unittest/test_parse_code_suggestion.py b/tests/unittest/test_parse_code_suggestion.py index 5ffd9f3e1..c959a2dcb 100644 --- a/tests/unittest/test_parse_code_suggestion.py +++ b/tests/unittest/test_parse_code_suggestion.py @@ -6,8 +6,8 @@ Code Analysis Objective: -The objective of the function is to convert a dictionary into a markdown format. The function takes in a dictionary as -input and recursively converts it into a markdown format. The function is specifically designed to handle dictionaries +The objective of the function is to convert a dictionary into a markdown format. The function takes in a dictionary as +input and recursively converts it into a markdown format. The function is specifically designed to handle dictionaries that contain code suggestions. Inputs: diff --git a/tests/unittest/test_try_fix_yaml.py b/tests/unittest/test_try_fix_yaml.py index 90fa63f12..336c4af5e 100644 --- a/tests/unittest/test_try_fix_yaml.py +++ b/tests/unittest/test_try_fix_yaml.py @@ -1,9 +1,9 @@ # Generated by CodiumAI -from pr_agent.algo.utils import try_fix_yaml +import pytest +from pr_agent.algo.utils import try_fix_yaml -import pytest class TestTryFixYaml: @@ -54,7 +54,7 @@ def test_no_initial_yaml(self): src/index.ts label: | best practice - + - relevant_file: | src/index2.ts label: | @@ -87,4 +87,4 @@ def test_with_initial_yaml(self): We can further improve the code by using the `const` keyword instead of `var` in the `src/index.ts` file. ''' expected_output = {'code_suggestions': [{'relevant_file': 'src/index.ts\n', 'label': 'best practice\n'}, {'relevant_file': 'src/index2.ts\n', 'label': 'enhancment'}]} - assert try_fix_yaml(review_text, first_key='code_suggestions', last_key='label') == expected_output \ No newline at end of file + assert try_fix_yaml(review_text, first_key='code_suggestions', last_key='label') == expected_output From 7c90e4465668704e14464c6b301d09126c2cbc89 Mon Sep 17 00:00:00 2001 From: Yu Ishikawa <yu-iskw@users.noreply.github.com> Date: Wed, 30 Oct 2024 10:00:42 +0900 Subject: [PATCH 3/4] Add pre-commit Signed-off-by: Yu Ishikawa <yu-iskw@users.noreply.github.com> --- requirements-dev.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 1af82d005..533ef1eb9 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,3 +1,4 @@ pytest==7.4.0 poetry -twine \ No newline at end of file +twine +pre-commit>=4,<5 From 852bb371afaaed601494e7e8bb3b148e6c6c42f8 Mon Sep 17 00:00:00 2001 From: Yu Ishikawa <yu-iskw@users.noreply.github.com> Date: Wed, 30 Oct 2024 10:00:59 +0900 Subject: [PATCH 4/4] Add `pre-commit.yml` Signed-off-by: Yu Ishikawa <yu-iskw@users.noreply.github.com> --- .github/workflows/pre-commit.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/workflows/pre-commit.yml diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 000000000..9018233d1 --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,15 @@ +name: pre-commit + +on: + pull_request: + push: + branches: [main] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v5 + # SEE https://github.com/pre-commit/action + - uses: pre-commit/action@v3.0.1
extra_instructions