Compare commits

...

527 Commits

Author SHA1 Message Date
7cf521c001 fix: improve null safety in GitLab webhook handler 2025-02-27 11:53:11 +02:00
Tal
e71c0f1805 Merge pull request #1586 from qodo-ai/tr/docs245
docs: add language configuration documentation and update changelog
2025-02-27 11:10:20 +02:00
8182a4afc0 docs: update default model to o3-mini and improve language configuration instructions 2025-02-27 11:06:31 +02:00
3817aa2868 fix: remove redundant temperature logging in litellm handler 2025-02-27 10:55:01 +02:00
94a8606d24 fix: update default configuration values for publishing and verbosity 2025-02-27 10:52:20 +02:00
af635650f1 fix: improve response language handling and configuration documentation 2025-02-27 10:50:28 +02:00
222f276959 docs: add language configuration documentation and update changelog 2025-02-27 10:29:05 +02:00
Tal
9a32e94b3e Merge pull request #1579 from qodo-ai/response-language-configuration
Add a language configuration to translate language generated by QodoM…
2025-02-27 08:01:13 +02:00
Tal
7c56eee701 Update README.md 2025-02-27 07:59:01 +02:00
Tal
48b3c69c10 Merge pull request #1575 from GOOD21/feature/draft-ready-trigger
gitlab webhook automatically trigger pr_command when MR changes from Draft to Ready
2025-02-27 07:57:12 +02:00
Tal
9d1c8312b5 Merge pull request #1584 from qodo-ai/tr/gitlab_fix
Tr/gitlab fix
2025-02-26 21:35:24 +02:00
64e5a87530 fix: improve error handling and null safety in PR description tool 2025-02-26 21:33:40 +02:00
9a9acef0e8 fix: handle empty commits and errors in GitLab provider's get_latest_commit_url 2025-02-26 21:24:53 +02:00
3ff8f1ff11 Add documentation 2025-02-26 18:45:24 +02:00
c7f4b87d6f Merge pull request #1583 from qodo-ai/hl/enhance_azure_devops
feat: enhance Azure DevOps integration with improved error handling a…
2025-02-26 17:17:31 +02:00
9db44b5f5f Update pr_agent/servers/azuredevops_server_webhook.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-26 17:16:07 +02:00
70a2377ac9 fix: make Azure DevOps webhook handler asynchronous 2025-02-26 17:13:38 +02:00
52a68bcd44 fix: adjust newline formatting in issue details summary 2025-02-26 16:49:44 +02:00
0a4c02c8b3 feat: enhance Azure DevOps integration with improved error handling and PR commands 2025-02-26 16:40:46 +02:00
e253f18e7f Remove default configuration 2025-02-26 14:43:56 +02:00
d6b6191f90 Remove uneccessary hardcoded configurations list 2025-02-26 14:42:32 +02:00
de80901284 Add a language configuration to translate language generated by QodoMerge, such as suggestions and desciption text 2025-02-26 14:37:15 +02:00
dfbd8dad5d Automatically trigger pr_command when MR changes from Draft to Ready 2025-02-26 18:12:48 +08:00
Tal
d6f405dd0d Merge pull request #1564 from chandan84/fix/support_litellm_extra_headers
Fix/support litellm extra headers
2025-02-26 10:15:22 +02:00
Tal
25ba9414fe Merge pull request #1561 from KennyDizi/main
Support reasoning effort via configuration
2025-02-26 10:13:05 +02:00
d097266c38 Fix typo in document 2025-02-26 07:57:22 +07:00
fa1eda967f Add document for OpenAI models dedicated parameters 2025-02-26 07:54:50 +07:00
c89c0eab8c Update changing_a_model.md
updated docs for extra_headers usage for litellm
2025-02-25 15:15:53 -05:00
93e34703ab Update litellm_ai_handler.py
updates made based on review on https://github.com/qodo-ai/pr-agent/pull/1564
2025-02-25 14:44:03 -05:00
c15ed628db Merge pull request #1572 from qodo-ai/hl/auto_approve_docs
docs: add auto-approve feature to platform support matrix
2025-02-25 13:54:44 +02:00
70f47336d6 link + add to readme 2025-02-25 13:41:06 +02:00
Tal
c6a6a2f352 Merge pull request #1570 from hirobf10/support-claude-3-7
feat: support Claude 3.7 Sonnet
2025-02-25 10:49:42 +02:00
1dc3db7322 Update pr_agent/algo/__init__.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-25 16:51:55 +09:00
049fc558a8 Update pr_agent/algo/__init__.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-25 16:51:50 +09:00
2dc89d0998 Update pr_agent/algo/__init__.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-25 16:51:39 +09:00
Tal
07bbfff4ba Update improve.md 2025-02-25 09:06:11 +02:00
Tal
328637b8be Merge branch 'main' into hl/auto_approve_docs 2025-02-25 09:05:30 +02:00
44d9535dbc docs: add auto-approve feature to platform support matrix 2025-02-25 09:02:45 +02:00
Tal
7fec17f3ff Merge pull request #1571 from qodo-ai/of/update-overview
Docs: fix static code and remove Incremental PR review
2025-02-25 08:56:55 +02:00
cd15f64f11 Merge branch 'main' into of/update-overview 2025-02-25 08:23:08 +02:00
d4ac206c46 docs: fix static code and remove Incremental PR review 2025-02-25 08:22:46 +02:00
Tal
444910868e Merge pull request #1555 from GOOD21/fix/push-events
Enhanced gitlab webhook handling for push events without object_attributes
2025-02-25 07:56:03 +02:00
a24b06b253 feat: support Claude 3.7 Sonnet 2025-02-25 12:58:20 +09:00
Tal
393516f746 Merge pull request #1556 from benedict-lee/main
Fix prompt to not output diff prefixes in existing_code,improved_code pydantic definitions
2025-02-24 22:10:30 +02:00
Tal
152b111ef2 Merge pull request #1568 from qodo-ai/tr/hunk_fallback
feat: improve patch extension with new file content comparison
2025-02-24 13:25:49 +02:00
56250f5ea8 feat: improve patch extension with new file content comparison 2025-02-24 11:46:12 +02:00
7b1df82c05 rollback : pr_code_suggestions_prompts.toml 2025-02-24 09:30:00 +09:00
05960f2c3f rollback : pr_code_suggestions_prompts.toml 2025-02-24 09:15:51 +09:00
feb306727e fix : refine handling of leading '+' in response text 2025-02-24 09:15:00 +09:00
2a647709c4 style: improve AI search UI and add dark mode support 2025-02-23 21:04:19 +02:00
Tal
a4cd05e71c Merge pull request #1566 from qodo-ai/tr/ai_search
Tr/ai search
2025-02-23 16:38:06 +02:00
da6ef8c80f feat: update docs search API endpoint to production URL 2025-02-23 16:31:06 +02:00
775bfc74eb feat: update docs search API endpoint to production URL 2025-02-23 16:29:24 +02:00
ebdbde1bca Merge branch 'main' into main 2025-02-23 21:26:44 +07:00
Tal
e16c6d0b27 Merge pull request #1565 from qodo-ai/tr/auto_approval_Docs
docs: add auto-approval configuration documentation
2025-02-23 08:36:11 +02:00
f0b52870a2 docs: update auto-approval feature documentation and configuration 2025-02-23 08:34:16 +02:00
Tal
1b35f01aa1 Merge pull request #1560 from qodo-ai/of/fix-improve-notes
Improve documentation formatting and readability
2025-02-23 08:19:28 +02:00
a0dc9deb30 docs: add auto-approval configuration documentation 2025-02-23 08:15:14 +02:00
7e32a08f00 Refresh implement image in README 2025-02-23 08:05:17 +02:00
84983f3e9d line 253-261, pass extra_headers fields from settings to litellm, exception handling to check if extra_headers is in dict format 2025-02-22 14:56:17 -05:00
71451de156 Update litellm_ai_handler.py
line 253-258, pass extra_headers fields from settings to litellm, exception handling to check if extra_headers is in dict format
2025-02-22 14:43:03 -05:00
0e4a1d9ab8 line 253-258, pass extra_headers fields from settings to litellm, exception handling to check if extra_headers is in dict format 2025-02-22 14:38:38 -05:00
e7b05732f8 line 253-255, pass extra_headers fields from settings to litellm 2025-02-22 14:12:39 -05:00
37083ae354 Improve logging for adding parameters: temperature and reasoning_effort 2025-02-22 22:19:58 +07:00
020ef212c1 docs: fix notes admonition syntax in documentation 2025-02-22 16:46:31 +02:00
01cd66f4f5 chore: comment out test_fetching_sub_issues.py due to API calls 2025-02-22 16:06:30 +02:00
af72b45593 docs: update repository URLs and name 2025-02-22 11:01:54 +02:00
9abb212e83 Add reasoning_effort argument to chat completion request 2025-02-21 22:16:18 +07:00
e81b0dca30 Support reasoning_effort via configuration file 2025-02-21 22:14:58 +07:00
d37732c25d Define ReasoningEffort enum 2025-02-21 22:10:49 +07:00
e6b6e28d6b Define SUPPORT_REASONING_EFFORT_MODELS list 2025-02-21 22:10:33 +07:00
5bace4ddc6 docs: final touches 2025-02-21 10:47:19 +02:00
b80d7d1189 Merge branch 'main' into of/fix-improve-notes 2025-02-21 10:38:21 +02:00
b2d8dee00a docs: improve formatting and readability of documentation 2025-02-21 10:38:18 +02:00
Tal
ac3dbdf5fc Merge pull request #1529 from WonOfAKind/feature/sub-issues-ticket-1499
Added sub-issue fetching to enhance PR analysis
2025-02-21 09:42:18 +02:00
f143a24879 remove unnecessary code 2025-02-21 13:35:48 +08:00
347af1dd99 use merge_request with oldrev instead of push 2025-02-21 13:24:20 +08:00
d91245a9d3 Update pr_agent/git_providers/github_provider.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-20 20:12:49 +02:00
bfdaac0a05 Update pr_agent/git_providers/github_provider.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-20 20:11:25 +02:00
183d2965d0 Update pr_agent/tools/ticket_pr_compliance_check.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-20 12:53:26 -05:00
86647810e0 Update pr_agent/tools/ticket_pr_compliance_check.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-20 12:53:17 -05:00
56978d9793 Update pr_agent/git_providers/github_provider.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-20 12:32:29 -05:00
6433e827f4 Update pr_agent/git_providers/github_provider.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-20 12:32:22 -05:00
c0e78ba522 Update pr_agent/git_providers/github_provider.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-20 12:32:14 -05:00
45d776a1f7 Update pr_agent/git_providers/github_provider.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-20 12:32:06 -05:00
6e19e77e5e Update pr_agent/git_providers/github_provider.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-20 12:31:25 -05:00
1e98d27ab4 docs: update custom prompt configuration parameter name 2025-02-20 18:38:18 +02:00
Tal
a47d4032b8 Merge pull request #1559 from qodo-ai/tr/date_review
feat: add current date to PR review metadata
2025-02-20 18:07:52 +02:00
2887d0a7ed refactor: move CLI argument validation to dedicated class 2025-02-20 17:51:16 +02:00
a07f6855cb feat: add current date to PR review metadata 2025-02-20 16:44:45 +02:00
237a6ffb5f fix : existing and improved code fields to clarify formatting requirements 2025-02-20 11:52:53 +09:00
5e1cc12df4 Enhanced webhook handling for push events without object_attributes 2025-02-20 10:47:21 +08:00
29a350b4f8 docs: remove deepseek-r1 from supported models list 2025-02-18 17:49:19 +02:00
Tal
6efcd61087 Merge pull request #1552 from qodo-ai/tr/custom_reasoning_model
docs
2025-02-18 17:41:59 +02:00
c7cafa720e docs 2025-02-18 17:04:55 +02:00
Tal
9de9b397e2 Merge pull request #1551 from qodo-ai/tr/custom_reasoning_model
feat: add support for custom reasoning models
2025-02-18 12:04:24 +02:00
Tal
35059cadf7 Update pr_agent/algo/ai_handlers/litellm_ai_handler.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-18 11:50:48 +02:00
Tal
0317951e32 Update pr_agent/settings/configuration.toml
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-18 11:48:25 +02:00
4edb8b89d1 feat: add support for custom reasoning models 2025-02-18 11:46:22 +02:00
Tal
a5278bdad2 Merge pull request #1550 from qodo-ai/AdamWalkerQodo-patch-1
Update README.md
2025-02-18 11:26:10 +02:00
3fd586c9bd Update README.md 2025-02-18 11:20:02 +02:00
717b2fe5f1 Update README.md
Rebranding
2025-02-18 09:32:15 +02:00
262c1cbc68 Merge remote-tracking branch 'origin/main' 2025-02-17 20:33:28 +02:00
defdaa0e02 docs: simplify and improve PR filtering documentation 2025-02-17 20:33:19 +02:00
Tal
5ca6918943 Merge pull request #1539 from yu-iskw/support-gemini-2.0
Support generally available `gemini-2.0-flash`
2025-02-17 19:47:50 +02:00
Tal
cfd813883b Merge pull request #1543 from qodo-ai/of/update-improve-docs
docs: add documentation for new `improve` `more` feature
2025-02-17 17:58:15 +02:00
Tal
c6d32a4c9f Merge pull request #1548 from qodo-ai/AdamWalkerQodo-patch-2
Update README.md
2025-02-17 17:57:33 +02:00
ae4e99026e Update README.md 2025-02-17 17:53:27 +02:00
Tal
42f493f41e Merge pull request #1547 from qodo-ai/AdamWalkerQodo-patch-1
Add files via upload
2025-02-17 17:29:11 +02:00
34d73feb1d Update README.md
Qodo Rebrand
2025-02-17 17:27:13 +02:00
ebc94bbd44 Add files via upload
Qodo Rebrand
2025-02-17 17:23:22 +02:00
Tal
4fcc7a5f3a Update README.md 2025-02-17 16:19:05 +02:00
Tal
41760ea333 Merge pull request #1546 from qodo-ai/revert-1545-AdamWalkerQodo-patch-1
Revert "Update README.md"
2025-02-17 16:11:33 +02:00
Tal
13128c4c2f Revert "Update README.md" 2025-02-17 16:11:20 +02:00
da168151e8 Merge pull request #1545 from qodo-ai/AdamWalkerQodo-patch-1
Approved by Dedy
2025-02-17 16:10:06 +02:00
a132927052 Update README.md
Updating images for Rebrand
2025-02-17 15:18:18 +02:00
b52d0726a2 docs: fix capitalization in improve tool configuration description 2025-02-17 12:37:13 +02:00
fc411dc8bc docs: add documentation for new improve more feature 2025-02-17 12:34:58 +02:00
22f02ac08c Support generally available gemini-2.0-flash
Signed-off-by: Yu Ishikawa <yu-iskw@users.noreply.github.com>
2025-02-17 08:40:05 +09:00
Tal
52883fb1b5 Merge pull request #1537 from KennyDizi/main
Refactoring `LiteLLMAIHandler` class for better using reasoning models
2025-02-16 19:50:03 +02:00
adfc2a6b69 Add temperature only if model supports it 2025-02-16 15:43:40 +07:00
c4aa13e798 Add o1-preview model to USER_MESSAGE_ONLY_MODELS and NO_SUPPORT_TEMPERATURE_MODELS 2025-02-16 15:18:52 +07:00
90575e3f0d Add NO_SUPPORT_TEMPERATURE_MODELS list 2025-02-16 15:17:59 +07:00
fcbe986ec7 Removed o3 model from USER_MESSAGE_ONLY_MODELS 2025-02-16 15:17:12 +07:00
061fec0d36 Removed o1 model from USER_MESSAGE_ONLY_MODELS 2025-02-16 15:15:50 +07:00
778d00d1a0 Merge remote-tracking branch 'origin/main' 2025-02-15 11:32:43 +02:00
cc8d5a6c50 docs: fix broken links in GitLab Server installation section 2025-02-15 11:32:32 +02:00
Tal
62c47f9cb5 Merge pull request #1536 from PeterDaveHelloKitchen/OptimizeDockerfile
Use `pip install` with `--no-cache-dir` in `Dockerfile.github_action`
2025-02-15 11:25:41 +02:00
bb31b0c66b docs: update Qodo Merge installation guide with GitLab Server details 2025-02-15 11:23:52 +02:00
Tal
359c963ad1 Merge pull request #1531 from hi120ki/add-pull-request-target-event
Add : pull_request_target event on GitHub Actions integration
2025-02-15 08:08:20 +02:00
130b1ff4fb Use pip install with --no-cache-dir in Dockerfile.github_action 2025-02-15 00:17:02 +08:00
Tal
605a4b99ad Merge pull request #1534 from qodo-ai/tr/help_r
feat: improve help tool with markdown header formatting and error han…
2025-02-13 11:50:59 +02:00
b989f41b96 fix: correct typo in help tool message ("be" -> "can be") 2025-02-13 11:48:07 +02:00
26168a605b fix: correct typo in help tool message ("be" -> "can be") 2025-02-13 11:47:21 +02:00
2c37b02aa0 feat: improve help tool with markdown header formatting and error handling 2025-02-13 11:44:50 +02:00
Tal
a2550870c2 Merge pull request #1532 from qodo-ai/tr/review_effort
fix: update review effort label format to use X/5 notation
2025-02-13 09:25:53 +02:00
279c6ead8f fix: update review effort label format to use X/5 notation 2025-02-13 08:41:25 +02:00
c9500cf796 Add : pull_request_target event on GitHub Actions integration
Signed-off-by: Hi120ki <12624257+hi120ki@users.noreply.github.com>
2025-02-13 12:03:30 +09:00
0f63d8685f Added sub-issue fetching to enhance PR analysis 2025-02-12 19:40:36 -05:00
77204faa51 docs: clarify open-source models usage scope in model selection guide 2025-02-11 10:24:16 +02:00
43fb8ff433 docs: fix broken link to Qodo Merge models documentation 2025-02-11 08:49:05 +02:00
cd129d8b27 docs: fix broken link to Qodo Merge models documentation 2025-02-11 08:47:04 +02:00
Tal
04aff0d3b2 Update README.md 2025-02-07 20:51:21 +02:00
Tal
be1dd4bd20 Update README.md 2025-02-06 18:10:37 +02:00
Tal
b3b89e7138 Merge pull request #1522 from qodo-ai/tr/readme_34
docs: update README with new design and remove outdated news
2025-02-06 18:06:17 +02:00
9045723084 docs: adjust Qodo Merge link formatting in README 2025-02-06 18:04:31 +02:00
34e22a2c8e docs: update image URL in README for /improve tool screenshot 2025-02-06 18:02:40 +02:00
1d784c60cb docs: update README with new design and remove outdated news 2025-02-06 17:59:40 +02:00
deffdbbb89 Merge pull request #1517 from qodo-ai/security_policy_md
Create SECURITY.md
2025-02-05 14:54:55 +02:00
b29a19957c Update SECURITY.md
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-05 14:54:32 +02:00
f209bc5323 Update SECURITY.md 2025-02-05 14:50:12 +02:00
32890fec20 Create SECURITY.md 2025-02-05 14:03:32 +02:00
Tal
9ddd7c967a Merge pull request #1515 from qodo-ai/create-code-of-conduct
Create CODE_OF_CONDUCT.md
2025-02-05 11:28:10 +02:00
Tal
245c3ad523 Update CODE_OF_CONDUCT.md
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-02-05 11:27:51 +02:00
43decd9ff2 Update CODE_OF_CONDUCT.md 2025-02-05 11:25:06 +02:00
Tal
3af84aab5b Merge pull request #1514 from qodo-ai/tr/improve_impact
feat: improve code suggestions table with impact levels and styling
2025-02-05 11:20:16 +02:00
3633863e90 Create CODE_OF_CONDUCT.md 2025-02-05 10:41:24 +02:00
69f19f1abd feat: improve code suggestions impact levels with configurable thresholds 2025-02-05 09:41:01 +02:00
400146985a feat: improve code suggestions table with impact levels and styling 2025-02-05 09:31:32 +02:00
24bf875db6 fix: handle GitHub permission errors when editing comments 2025-02-03 07:51:44 +02:00
9687b4df70 docs: update model selection guide with supported models list 2025-02-03 07:31:02 +02:00
Tal
d8fba02b48 Merge pull request #1509 from KennyDizi/main
Define user_message_only_models list for using user prompt only model
2025-02-02 16:14:05 +02:00
a6482c37ce Add o3-mini to user message only model list 2025-02-02 18:03:38 +07:00
83582bc935 Add support o3-mini model 2025-02-02 18:02:53 +07:00
4ac1e15bae Refactoring user messages only flow 2025-02-02 18:01:44 +07:00
a48686bde9 Define USER_MESSAGE_ONLY_MODELS in the algo init file 2025-02-02 18:01:16 +07:00
7168d16386 Remove user_message_only_models from configuration file 2025-02-02 18:00:34 +07:00
Tal
dc21f71ee2 Merge pull request #1510 from PeterDaveHelloKitchen/OptimizeDockerfile
Use `pip install` with `--no-cache-dir` in Dockerfiles
2025-02-02 07:30:13 +02:00
7127a030b2 fix: improve error logging in GitHub polling service 2025-02-01 19:47:54 +02:00
8f340bce67 Use pip install with --no-cache-dir in Dockerfiles
This will help minimize the Docker image size, as below:

```
REPOSITORY    TAG       IMAGE ID         CREATED        SIZE
pr-agent      after     caed11a1ed9c     2 hours ago    1.48GB
pr-agent      before    d6f12eb987b8     3 hours ago    1.59GB
```
2025-02-02 00:29:52 +08:00
48377e3c81 Add a null check for user_message_only_models before using it 2025-01-31 11:53:05 +07:00
7eb26b3220 Check current model is in user_message_only_models list 2025-01-31 11:25:51 +07:00
32ccb25575 Add user_message_only_models 2025-01-31 11:24:43 +07:00
9aafe18f01 docs: add platform support notice for implement tool 2025-01-30 12:24:14 +02:00
Tal
4df9e03c4c Merge pull request #1506 from qodo-ai/tr/fallback
fix: add fallback for parsing AI responses with leading '+' symbols
2025-01-30 11:56:04 +02:00
136c75a5ac fix: add fallback for parsing AI responses with leading '+' symbols 2025-01-30 08:35:31 +02:00
91b0f11cf2 docs: add link to article about effective AI code suggestions 2025-01-30 07:44:09 +02:00
Tal
50740f080b Merge pull request #1500 from qodo-ai/of/add-contributing-file
Add CONTRIBUTING.md with contribution guidelines and setup instructions
2025-01-28 15:39:49 +02:00
ad5308c0a3 docs: add CONTRIBUTING.md with development guidelines and setup instructions 2025-01-28 11:55:27 +02:00
Tal
f383709629 Merge pull request #1498 from qodo-ai/tr/issue_formatting
fix: update issue template fields and Discord link
2025-01-28 10:07:18 +02:00
4d7fe07c16 fix: update issue template fields and Discord link 2025-01-28 09:59:59 +02:00
Tal
456d5aa233 Merge pull request #1495 from qodo-ai/of/issue_template
fix: remove shell rendering from issue templates
2025-01-28 09:21:13 +02:00
d50bfa4b06 fix: remove shell rendering from issue templates 2025-01-28 09:18:02 +02:00
7393887381 Merge remote-tracking branch 'origin/main' 2025-01-28 08:36:47 +02:00
9da4c9d776 fix: correct typo in code suggestions label description 2025-01-28 08:36:36 +02:00
Tal
251b4a6395 Update README.md 2025-01-28 03:29:44 +02:00
Tal
d85725c636 Merge pull request #1490 from qodo-ai/of/issues-fixes
Update config.yml
2025-01-27 16:25:24 +02:00
6ef586a617 Update miscellaneous.yml 2025-01-27 16:24:40 +02:00
43991df2c4 Update bug-report.yml 2025-01-27 16:23:48 +02:00
231d5c20d5 Update config.yml 2025-01-27 16:22:35 +02:00
Tal
9052cec391 Merge pull request #1478 from qodo-ai/of/issue_template
Add GitHub issue templates for bug reports and feature requests
2025-01-27 16:21:17 +02:00
Tal
33ed6927fc Update .github/ISSUE_TEMPLATE/miscellaneous.yml
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-01-27 16:21:11 +02:00
62aaeb267a Update bug-report.yml 2025-01-27 16:20:24 +02:00
a7bea3b166 feat: add miscellaneous issue template and update template configurations 2025-01-27 16:17:33 +02:00
b81d686561 Update feature-request.yml 2025-01-27 16:02:29 +02:00
e5e30f7bd3 Update bug-report.yml 2025-01-27 16:00:03 +02:00
4bfd845877 docs: add wiki requirement notice for auto best practices feature 2025-01-27 10:07:30 +02:00
e8a80264ca fix: improve GitLab help message formatting with proper line breaks 2025-01-26 16:54:17 +02:00
75f4c7f681 Merge branch 'tr/docs_best_practice' 2025-01-26 16:42:48 +02:00
Tal
2277a31661 Merge pull request #1485 from qodo-ai/tr/docs_best_practice
Tr/docs best practice
2025-01-26 16:40:09 +02:00
805d9cac69 docs: add auto best practices diagrams and wiki usage explanation 2025-01-26 16:39:25 +02:00
Tal
beffa8dfe4 Merge pull request #1486 from qodo-ai/hl/update_ticket_analysis
feat: enhance ticket compliance analysis with human verification tracking
2025-01-26 15:58:22 +02:00
a42c5f4f93 feat: limit number of tickets to analyze to 3 in compliance check 2025-01-26 14:31:29 +02:00
63c98d30d9 docs: simplify wording and clarify exploration concept in best practices guide 2025-01-26 12:57:53 +02:00
50c52e32c9 enter
feat: enhance ticket compliance analysis with human verification tracking
2025-01-26 12:33:49 +02:00
f48c95d113 order 2025-01-26 12:10:30 +02:00
2ead9fe4df typo 2025-01-26 12:07:48 +02:00
4d52715d25 docs: add auto best practices documentation and configuration 2025-01-26 12:02:27 +02:00
84d81deac0 Merge branch 'main' into of/issue_template 2025-01-26 09:23:54 +02:00
83baac975d docs: clarify code suggestion prompt field description for existing code 2025-01-26 09:16:52 +02:00
Tal
3f6fa5cccb Merge pull request #1484 from qodo-ai/of/add-implement-to-help
Add `IMPLEMENT` tool and reorganize help message content
2025-01-25 08:57:47 +02:00
a7fbd694cc docs: add January 2025 organization update notice and fix typo in prompts 2025-01-25 08:54:57 +02:00
78b11fca4c feat: add implement tool to help message and reorder tools list 2025-01-24 17:13:37 +02:00
640c1d8dda refactor: update review effort label format to include range indicator 2025-01-23 21:44:56 +02:00
dfa98cdfa3 Merge remote-tracking branch 'origin/main' 2025-01-23 16:59:14 +02:00
5518f1ca26 docs: update repository URLs from Codium-ai to qodo-ai 2025-01-23 16:59:04 +02:00
Tal
c4a70f4852 Update .github/ISSUE_TEMPLATE/bug-report.yml
Co-authored-by: qodo-merge-pro[bot] <151058649+qodo-merge-pro[bot]@users.noreply.github.com>
2025-01-23 16:52:22 +02:00
Tal
363ea3eec8 Update .github/ISSUE_TEMPLATE/bug-report.yml
Co-authored-by: qodo-merge-pro[bot] <151058649+qodo-merge-pro[bot]@users.noreply.github.com>
2025-01-23 16:51:12 +02:00
97cbfe1c2b fix: update issue template labels and descriptions for git providers and bug types 2025-01-23 16:27:26 +02:00
68f2198549 feat: update issue template dropdowns for git providers and task types 2025-01-23 16:11:30 +02:00
20bbe4187a docs: reorder contact links in issue template config 2025-01-23 15:57:13 +02:00
2f69c8989c clean-up 2025-01-23 13:38:02 +02:00
ed102dc730 feat: add GitHub issue templates for bug reports and feature requests 2025-01-23 13:35:30 +02:00
Tal
c2bad8ab29 Update index.md 2025-01-23 12:24:09 +02:00
e9c1c91a4b feat: enhance help message formatting and support for different git providers 2025-01-23 12:05:07 +02:00
Tal
eba116fedd Merge pull request #1477 from qodo-ai/tr/shorter_label
refactor: simplify review effort label format and remove maximal effo…
2025-01-23 11:49:11 +02:00
94616a3429 refactor: simplify review effort label format and remove maximal effort limit 2025-01-23 11:20:58 +02:00
c1fa22d068 refactor: simplify review effort label format and remove maximal effort limit 2025-01-23 11:18:00 +02:00
4f1e4073e4 docs: fix wording in local installation guide 2025-01-23 09:08:38 +02:00
Tal
b320767c97 Merge pull request #1475 from Codium-ai/tr/docs24
docs: reorganize installation documentation structure
2025-01-23 08:53:44 +02:00
cd5bdf9e59 docs: reorganize token requirements in installation documentation 2025-01-23 08:53:29 +02:00
e8b8909ab7 docs: update pricing link from codium.ai to qodo.ai 2025-01-23 08:47:20 +02:00
ee8cdcf2b2 docs: reorganize installation documentation structure 2025-01-23 08:45:47 +02:00
Tal
1cb21c6615 Merge pull request #1473 from KennyDizi/main
Add support model deepseek/deepseek-reasoner
2025-01-23 08:07:53 +02:00
Tal
b5f52c5fea Merge pull request #1469 from gryphon-ops/main
Remove false log that file was modified, but no patch found for bitbucket server
2025-01-23 08:03:35 +02:00
4e481c5088 docs: rebrand from Qodo Merge to PR-Agent in installation guides 2025-01-22 21:28:29 +02:00
Tal
7367c00c3d Merge pull request #1474 from Codium-ai/tr/docs23
QM
2025-01-22 21:21:39 +02:00
fb3aa8c96c docs: fix punctuation in Chrome extension documentation 2025-01-22 21:20:44 +02:00
983ce131f2 docs: rebrand from Qodo Merge Pro to Qodo Merge throughout documentation 2025-01-22 21:18:08 +02:00
e571841b5c docs: clarify distinction between PR-Agent and Qodo Merge throughout documentation 2025-01-22 21:11:46 +02:00
Tal
c537e9ff66 Merge pull request #1471 from Codium-ai/of/rebrand-readme
README: Replace Codium and PR-Agent with Qodo and Qodo-Merge
2025-01-22 17:07:07 +02:00
fc5454630a docs: rebrand from Qodo-Merge to PR-Agent in README 2025-01-22 16:39:14 +02:00
c2ca79da0d Combining system and user prompts for o1 series and deepseek-reasoner models 2025-01-22 20:33:43 +07:00
63f1d449ce Add support model deepseek/deepseek-reasoner 2025-01-22 20:32:18 +07:00
0adaddccdf docs: update branding from PR-Agent to Qodo-Merge in README 2025-01-22 14:35:13 +02:00
8a1f07dd6b docs: clarify Qodo-Merge's open-source nature in README 2025-01-22 14:24:40 +02:00
8e5d2a0f4d docs: update branding from PR-Agent to Qodo-Merge in README 2025-01-22 14:18:23 +02:00
4e1cae3869 docs: remove redundant row number in feature table 2025-01-22 10:16:05 +02:00
7be26b665e docs: update branding from PR-Agent to Qodo-Merge in README 2025-01-22 10:12:32 +02:00
664f1938c9 Remove false log that file was modified, but no patch found for bitbucket server 2025-01-20 14:56:10 -05:00
e0b6db9bec docs: standardize platform support notation in documentation 2025-01-20 19:39:15 +02:00
Tal
2f2cdd787d Merge pull request #1466 from yu-iskw/add-gemini-models
Add `vertex_ai/gemini-2.0-flash-exp`
2025-01-20 19:33:38 +02:00
Tal
2b25053de8 Merge pull request #1467 from Codium-ai/tr/open_on_new_window
docs: add target blank to external links in documentation
2025-01-20 14:48:38 +02:00
054957fcfe docs: add target blank to external links in documentation 2025-01-20 13:58:26 +02:00
0075084a22 Add vertex_ai/gemini-2.0-flash-exp
Signed-off-by: Yu Ishikawa <yu-iskw@users.noreply.github.com>
2025-01-20 18:29:37 +09:00
Tal
e62db20c1e Merge pull request #1465 from Codium-ai/tr/prompts
docs: improve diff format documentation and code review instructions
2025-01-19 20:13:47 +02:00
67d4c96166 fix: correct typos in code suggestions prompt 2025-01-19 17:21:48 +02:00
b335cacffd fix: limit one_sentence_summary to 6 words in code suggestions 2025-01-19 17:15:02 +02:00
87a5a7e156 fix: improve code review guidelines and clarify scope limitations 2025-01-19 17:10:04 +02:00
24aa15f074 fix: correct typo in diff format documentation 2025-01-19 15:11:56 +02:00
ad4a96caf1 docs: add wiki setup guide and update best practices documentation 2025-01-19 15:05:38 +02:00
e7f874a4b2 docs: improve diff format documentation and code review instructions 2025-01-19 14:37:49 +02:00
Tal
4ab9392042 Merge pull request #1455 from polacekpavel/fix/local-git-provider-method-stubs
fix(local_git): add interface func stubs for git local provider
2025-01-18 10:33:37 +02:00
Tal
536d97b9da Merge pull request #1457 from KennyDizi/main
Support deepseek-chat model
2025-01-18 10:32:12 +02:00
cea1b58714 Update document with change deepseek-chat model 2025-01-17 11:50:42 +07:00
5ed260d885 Add deepseek configuration block 2025-01-17 11:43:20 +07:00
e58a535594 Inject deepseek key to DEEPSEEK_API_KEY environment variable 2025-01-17 11:43:06 +07:00
d949f440a8 Add support model deepseek/deepseek-chat 2025-01-17 11:42:36 +07:00
4923c8d810 feat: add support for ignoring PRs from specific users 2025-01-16 08:34:01 +02:00
fe6540275c fix(local_git): add interface method stubs for local git provider compatibility 2025-01-15 18:19:36 +01:00
1997da3aac Merge pull request #1454 from Codium-ai/hl/jira_datacenter_docs
documentation
2025-01-15 17:26:07 +02:00
d0c442b74b enter 2025-01-15 17:24:37 +02:00
1f86cbc942 typo 2025-01-15 17:23:20 +02:00
633a1c7bd0 documentation 2025-01-15 17:03:31 +02:00
2d9141adad Merge pull request #1450 from Codium-ai/of/implement-tool-bitbucket
docs: add BitBucket support for /implement tool.
2025-01-15 08:10:16 +02:00
95d0d4d71d docs: add final_update_message configuration option documentation 2025-01-15 08:00:20 +02:00
Tal
5daf8e043c Merge pull request #1452 from med8bra/patch-1
fix(azure-provider): handle renamed files as new files
2025-01-14 11:04:40 +02:00
bd611bc1c2 fix(azure-provider): handle renamed files as new files
This fixes a bug when azure-provider tries to fetch original content of a renamed file and fails since the file doesn't exist in base yet.
Also handles case when `diff_type` includes multiple actions as `edit, rename`.

This can be improved to fetch the actual old content using the old path before renaming, but IMO for azure devops since its dying anyway, this fix should be enough.
2025-01-13 22:22:13 +01:00
4bb04e37c2 docs: add BitBucket support for /implement tool. 2025-01-13 13:29:59 +02:00
Tal
b3f116bb35 Merge pull request #1448 from pdecat/docs/typo
docs: add missing word
2025-01-10 20:14:23 +02:00
d15d08bb3b docs: add missing word 2025-01-10 16:08:04 +01:00
445a7fc015 filtering fix 2025-01-09 12:16:31 +02:00
Tal
c1c5c353e5 Merge pull request #1446 from Codium-ai/tr/avoid_packages_comments
fix: refine code suggestions prompts and avoid package-related comments
2025-01-08 22:12:57 +02:00
a74fca7b7d fix: refine code suggestions prompts and avoid package-related comments 2025-01-08 17:42:07 +02:00
Tal
7479ae3224 Merge pull request #1441 from benedict-lee/fix/support-aititle-with-markers
fix : support ai title with markers
2025-01-07 12:29:39 +02:00
Tal
6bb5ce58f2 Merge pull request #1442 from benedict-lee/fix/pr-type-rendering-with-markers
fix : pr type rendering with markers
2025-01-07 08:39:37 +02:00
2783f9b1bb Merge pull request #1440 from Codium-ai/of/implement-gitlab-documentation
docs: add GitLab support for /implement tool.
2025-01-06 13:35:23 +02:00
f4b895d870 fix : pr type rendering with markers
list obj to comma seperated pr types
2025-01-06 12:49:30 +09:00
07d40e2c05 fix : support ai title with markers 2025-01-06 12:42:12 +09:00
6e1178b168 Merge branch 'main' into of/implement-gitlab-documentation 2025-01-05 12:17:25 +02:00
Tal
c889e566e8 Merge pull request #1439 from Codium-ai/tr/patch_bug
fix: handle newline issues in patch generation
2025-01-05 12:16:08 +02:00
d9540d3b43 docs: add GitLab support for /implement tool. 2025-01-05 11:53:52 +02:00
793f76fec5 fix: add missing newlines at the end of patch strings in tests 2025-01-04 16:34:35 +02:00
5adc246040 Merge remote-tracking branch 'origin/tr/patch_bug' into tr/patch_bug 2025-01-04 16:30:47 +02:00
d4d58babd5 fix: handle empty inputs in patch generation 2025-01-04 16:30:33 +02:00
Tal
2df4bc8b53 Update pr_agent/algo/utils.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-01-04 16:28:25 +02:00
e431979b8b fix: handle newline issues in patch generation 2025-01-04 16:26:38 +02:00
Tal
bde594c9e8 Update README.md 2025-01-02 16:52:26 +02:00
b570c758aa docs: improve /implement tool documentation and update news section 2025-01-02 16:49:59 +02:00
Tal
f6b80174b5 Merge pull request #1434 from Codium-ai/tr/ollama
Tr/ollama
2025-01-02 16:26:46 +02:00
833ae67820 Merge branch 'main' into tr/ollama 2025-01-02 14:21:07 +02:00
Tal
ee913336ad Merge pull request #1433 from Codium-ai/fix-implement-docs
Refine `implement` tool documentation and remove outdated notes
2025-01-02 14:01:00 +02:00
79d589e145 Adjust image widths in /implement tool documentation 2025-01-02 12:56:55 +02:00
2d4cd3e270 Merge remote-tracking branch 'origin/main' into tr/ollama 2025-01-02 12:51:40 +02:00
7f950a3aa9 docs: clarify model recommendation for production usage 2025-01-02 12:50:38 +02:00
379fa957ea docs: clarify model recommendation for production usage 2025-01-02 12:48:56 +02:00
a1a7c8e44c feat: add example output duplication option for code suggestions prompts 2025-01-02 12:46:50 +02:00
6d0ed06fc4 Refine /implement tool documentation and remove language support notes 2025-01-02 12:39:14 +02:00
e695af6917 feat: add example output duplication option for PR review prompts 2025-01-02 12:33:26 +02:00
5318047202 feat: add prompt example duplication option for improved model output 2025-01-02 12:25:42 +02:00
Tal
5bf5f63c78 Merge pull request #1417 from ofir-frd/add-implement-documentation-
Add documentation for `/implement` tool and enhance `/test` tool references
2025-01-02 11:53:58 +02:00
5971a06d73 docs: improve Ollama and Hugging Face model configuration docs 2025-01-02 11:16:21 +02:00
71e477a993 docs: standardize language support notes across documentation files 2025-01-02 11:02:26 +02:00
efc621a58b fix: update Test tool link to correct documentation file 2025-01-02 10:55:30 +02:00
951fa3385a Merge branch 'main' into add-implement-documentation- 2025-01-02 10:52:31 +02:00
56e15c0348 Add a blank line at the end of the .gitignore file 2025-01-02 10:47:28 +02:00
4c82b8a43e docs: Add /implement tool to feature tables and documentation links 2025-01-02 10:44:50 +02:00
2d5daf4364 docs: Enhance /implement tool documentation with usage scenarios and examples 2025-01-02 10:34:04 +02:00
Tal
aa95d5fb68 Merge pull request #1432 from Codium-ai/tr/describe
fix: reorganize PR description prompt fields and improve clarity
2025-01-02 08:46:39 +02:00
f6b470bf5e fix: reorganize PR description prompt fields and improve clarity 2025-01-02 08:41:25 +02:00
Tal
36df75ce14 Merge pull request #1431 from Codium-ai/tr/protections23
fix: improve CLI argument validation for sensitive parameters
2025-01-01 16:10:30 +02:00
e2be1f1cee fix: improve CLI argument validation for sensitive parameters with dot notation 2025-01-01 15:53:37 +02:00
d1caa0f15f fix: improve CLI argument validation for sensitive parameters with dot notation 2025-01-01 15:52:54 +02:00
2c2af93eed fix: improve CLI argument validation for sensitive parameters 2025-01-01 15:19:27 +02:00
Tal
04197a9271 Merge pull request #1430 from Codium-ai/tr/faq_update
docs: update FAQ with new questions and improve formatting
2025-01-01 09:30:13 +02:00
Tal
9faf1521b4 Update docs/docs/faq/index.md
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2025-01-01 09:28:23 +02:00
Tal
8819293770 Merge pull request #1406 from vishwamartur/support-personal-spaces
Support pull requests in personal spaces in Bitbucket Server
2025-01-01 09:26:29 +02:00
0ec4491542 docs: update FAQ with new questions and improve formatting 2025-01-01 09:24:20 +02:00
Tal
4fd121d34a Merge pull request #1429 from Codium-ai/tr/sub_bullet_points
fix: improve PR description and title field descriptions for clarity
2024-12-31 12:35:09 +02:00
6e80f5fcce fix: improve file path formatting in patch headers 2024-12-31 12:31:21 +02:00
4a1b042152 fix: improve bullet point formatting and file path display in PR description 2024-12-31 12:00:21 +02:00
6fbd95e1a9 fix: emphasize brevity in PR description bullet points 2024-12-31 08:36:32 +02:00
fd6e81978f fix: improve PR description and title field descriptions for clarity 2024-12-31 08:32:54 +02:00
Tal
467136a48a Merge pull request #1428 from Codium-ai/mrT23-patch-7
Update README.md
2024-12-30 21:12:46 +02:00
Tal
3b14d3a3c2 Update README.md 2024-12-30 21:11:40 +02:00
Tal
8218fa6e13 Merge pull request #1421 from dceoy/main
Update Groq models and tokens
2024-12-30 19:25:23 +02:00
8463c4f549 fix: sanitize Ask tool answers to prevent markdown formatting issues with leading slashes 2024-12-30 16:54:03 +02:00
Tal
014b1f20c5 Merge pull request #1426 from Codium-ai/tr/ask_fix
fix: sanitize Ask tool answers to prevent markdown formatting issues
2024-12-30 15:12:28 +02:00
2f73ab6eab fix: sanitize Ask tool answers to prevent markdown formatting issues with leading slashes 2024-12-30 15:06:27 +02:00
16dc29a23a fix: sanitize Ask tool answers to prevent markdown formatting issues 2024-12-30 14:58:53 +02:00
bd9522057f fix: add OpenAI configuration parameters to restricted CLI arguments 2024-12-30 14:33:26 +02:00
Tal
b3d4af6cbf Merge pull request #1425 from Codium-ai/tr/limit_online_commenting
fix: restrict sensitive configuration parameters in CLI arguments
2024-12-30 14:11:28 +02:00
5df9698bae fix: restrict sensitive configuration parameters in CLI arguments 2024-12-30 13:57:55 +02:00
e89b65ed38 Increase the max token of groq/llama-3.3-70b-versatile 2024-12-30 11:35:02 +09:00
6a145af159 fix: make semantic file types extension optional in PR description 2024-12-29 21:43:46 +02:00
Tal
39a375b3e4 Merge pull request #1423 from Codium-ai/tr/describe_v2
Tr/describe v2
2024-12-29 16:02:03 +02:00
dbd76ecde5 refactor: improve file changes title description length guidance 2024-12-29 11:42:05 +02:00
e95920c58c refactor: improve file handling and description generation in PR description tool 2024-12-29 11:37:05 +02:00
59899f0c62 fix: improve patch generation error handling and logging 2024-12-29 11:27:53 +02:00
5e46955d52 fix: improve file path formatting in patch output 2024-12-29 11:26:13 +02:00
95d0fafa75 refactor: optimize file content loading and improve rate limit handling 2024-12-29 11:25:33 +02:00
71c558d306 Update Groq models and tokens 2024-12-28 01:51:33 +09:00
Tal
7b2c41e0d2 Merge pull request #1420 from Codium-ai/tr/review_fix
fix: improve line extraction from files with missing content
2024-12-27 09:02:41 +02:00
4aad67b563 fix: improve line extraction from files with missing content 2024-12-27 09:00:20 +02:00
0f973681ea Add /implement tool to README and fix /test tool link 2024-12-25 11:43:23 +02:00
19f6078ed0 Add /test tool to tools section and fix typos 2024-12-25 11:39:53 +02:00
3994a2ba60 Add .qodo to gitignore 2024-12-25 11:34:54 +02:00
796b36f0d1 Add documentation for /implement tool in tools section and related files 2024-12-25 11:34:41 +02:00
Tal
12d603fdb4 Update README.md 2024-12-25 08:42:24 +02:00
Tal
6540e2c674 Merge pull request #1416 from Codium-ai/tr/remove_review_suggestions
refactor: remove legacy code suggestions feature from review tool
2024-12-25 08:26:03 +02:00
83e68f168a log verbosity 2024-12-25 08:22:53 +02:00
5e1b04980e refactor: remove reflection and incremental review features from docs and code 2024-12-25 08:21:33 +02:00
495c1ebe5f refactor: remove legacy code suggestions feature from review tool 2024-12-25 08:18:28 +02:00
Tal
ad71de82a9 Merge pull request #1413 from addianto/docs/1398-environment-variables
Document an example on how to configure PR Agent using environment variables
2024-12-24 21:25:54 +02:00
11676943b6 docs: Remind user to avoid commiting .env file (#1398) 2024-12-24 15:20:15 +07:00
b88507aa23 chore: Ignore .env file 2024-12-24 15:14:30 +07:00
a5c5e6f4ae docs: Add example how to define environment variables (#1398) 2024-12-24 15:01:26 +07:00
47cd361663 docs: Mention about the use of Dynaconf (#1398) 2024-12-24 15:01:13 +07:00
Tal
c84b3d04b9 Merge pull request #1412 from Codium-ai/tr/dedent_review
feat: add dedent option to code snippet formatting
2024-12-24 07:54:36 +02:00
7d9288bb1a feat: add dedent option to code snippet formatting 2024-12-24 07:49:27 +02:00
Tal
93e64367d2 Merge pull request #1410 from Codium-ai/tr/update_changelog_fix
Tr/update changelog fix
2024-12-23 19:37:28 +02:00
6c131b8406 feat: add PR link support in changelog updates 2024-12-23 19:35:52 +02:00
dd89e1f2dc feat: add PR link support in changelog updates 2024-12-23 19:34:21 +02:00
e8e4fb0afa feat: add PR link support in changelog updates 2024-12-23 17:20:29 +02:00
3360a28b3e fix: improve changelog update prompt and response handling 2024-12-23 17:06:21 +02:00
Tal
20c506d2e0 Merge pull request #1402 from KennyDizi/main
Add support for OpenAI `o1` model and snapshot version `o1-2024-12-17`
2024-12-22 09:36:04 +02:00
Tal
a1921d931c Merge pull request #1407 from Codium-ai/tr/publish_output_no_suggestions_fix
fix: only publish empty code suggestions when configured
2024-12-22 09:34:34 +02:00
31aa460f5f fix: only publish empty code suggestions when configured 2024-12-22 09:32:11 +02:00
23678c1d4d Update O1_MODEL_PREFIX to o1 based on new models released 2024-12-22 10:36:59 +07:00
8d7825233a Supported model gpt-o1 2024-12-22 10:33:26 +07:00
4688b20284 Support pull requests in personal spaces in Bitbucket Server
Related to #1148

Update `_parse_pr_url` method in `pr_agent/git_providers/bitbucket_server_provider.py` to handle URLs with `/users/`.

* Add logic to check for both `/projects/` and `/users/` in the URL path and process them accordingly.
* Modify the method to raise a `ValueError` if neither `/projects/` nor `/users/` is found in the URL.
* Update the `workspace_slug` to include a `~` prefix if the URL contains `/users/`.

Add test case for URL with `/users/` in `tests/unittest/test_bitbucket_provider.py`.

* Ensure the new test case verifies the correct parsing of URLs with `/users/`.
2024-12-22 00:42:11 +05:30
Tal
c9f02e63e1 Merge pull request #1403 from Codium-ai/tr/re_review
feat: enhance code review output with collapsible code snippets
2024-12-20 16:38:56 +02:00
c2f1f2dba0 fix: improve markdown rendering when git provider is unavailable 2024-12-19 21:08:27 +02:00
3ab2cac089 fix: improve markdown rendering when git provider is unavailable 2024-12-19 20:59:17 +02:00
989670b159 fix: improve markdown rendering when git provider is unavailable 2024-12-19 20:49:40 +02:00
7e8361b5fd feat: enhance code review output with collapsible code snippets and variable links 2024-12-19 20:30:56 +02:00
eaaaf6a6a2 Fix context windows token for model o1-2024-12-17 2024-12-19 23:11:45 +07:00
07f3933f6d Add support OpenAI model o1 snapshot version o1-2024-12-17 2024-12-19 23:00:47 +07:00
Tal
84786495ed Merge pull request #1401 from Codium-ai/tr/docs3
docs: simplify default tool configurations and update documentation
2024-12-19 16:43:25 +02:00
d09aa1b13e docs: remove unused automatic_review configuration option 2024-12-19 16:41:18 +02:00
Tal
e9615c6994 Merge pull request #1384 from MarkRx/feature/version-metadata
Add --version command and version metadata
2024-12-19 09:34:24 +02:00
f3ee4a75b5 docs: simplify default tool configurations and update documentation 2024-12-19 09:33:20 +02:00
452abe2e18 Move get_version to algo/util.py; fix version to 0.25 2024-12-17 08:44:53 -07:00
Tal
a768969d37 Merge pull request #1397 from KennyDizi/main
Add support for `gemini/gemini-2.0-flash-exp` model
2024-12-16 20:37:55 +02:00
Tal
9ef9198468 Update index.md 2024-12-16 20:37:09 +02:00
Tal
d0ea901bca Update fetching_ticket_context.md 2024-12-16 20:29:17 +02:00
Tal
57089c931b Merge pull request #1396 from ofir-frd/add-pr-body-license-documentation
Similar Code: Add PR Body License Documentation
2024-12-16 20:24:42 +02:00
03d2bea50b Add support model gemini-2.0-flash-exp 2024-12-16 23:37:19 +07:00
721d38d4ed docs: add license information to similar code documentation 2024-12-16 17:11:17 +02:00
Tal
bbec5d9cc9 Merge pull request #1395 from Codium-ai/mrT23-patch-6
Update review.md
2024-12-14 11:54:56 +02:00
Tal
0be2750dfa Update review.md 2024-12-14 11:53:47 +02:00
Tal
5e5c251cd0 Merge pull request #1394 from Codium-ai/mrT23-patch-6
Update README.md
2024-12-13 16:11:12 +02:00
Tal
048ae8ee9e Update README.md
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2024-12-13 16:11:04 +02:00
Tal
1a77e9afaf Update README.md 2024-12-13 16:09:18 +02:00
Tal
184a52d325 Update README.md 2024-12-12 21:40:04 +02:00
Tal
3d38060dff Update README.md 2024-12-12 21:35:56 +02:00
c4dc263f2c docs: update repository reference to be platform-agnostic 2024-12-11 18:31:49 +02:00
Tal
f67cc0dd18 Merge pull request #1392 from Codium-ai/tr/model_weak
docs: remove model_weak configuration and simplify model selection
2024-12-11 18:19:05 +02:00
872b27bfd8 docs: remove model_weak configuration and simplify model selection 2024-12-11 18:10:34 +02:00
Tal
cb88489dbe Merge pull request #1387 from KennyDizi/main
Introduce to weak model
2024-12-11 17:36:18 +02:00
Tal
da786b8020 Merge pull request #1391 from Codium-ai/tr/thumbs_up_down
feat: add thumbs up/down support and refactor code suggestions handling
2024-12-11 13:21:07 +02:00
6a51b8501d docs: add allow_thumbs_up_down configuration option and remove rank_extended_suggestions 2024-12-11 13:16:21 +02:00
d34edb83ff feat: add thumbs up/down support and refactor code suggestions handling 2024-12-11 13:03:43 +02:00
Tal
c6eb253ed1 Merge pull request #1390 from glebzhidkov/docs/escape-list-in-yaml-file
Fix doc for Github Actions
2024-12-10 22:07:55 +02:00
a61f1889d1 fix doc 2024-12-10 13:44:56 +01:00
75a120952c Add version metadata and --version command 2024-12-09 09:27:54 -07:00
f9a7b18073 Improve condition to pick up weak model 2024-12-09 22:36:07 +07:00
6352e6e3bf Change default model to regular model 2024-12-09 22:24:44 +07:00
f49217e058 docs: fix typos in improve.md documentation 2024-12-09 09:09:09 +02:00
Tal
e11cec7d9e Merge pull request #1388 from Codium-ai/tr/readme_enhancments
docs: reorganize and enhance best practices documentation in improve.md
2024-12-09 09:05:25 +02:00
c45cde93ef docs: fix typos in improve.md documentation 2024-12-09 09:04:53 +02:00
9e25667d97 docs: reorganize and enhance best practices documentation in improve.md 2024-12-09 09:02:40 +02:00
7dc9e73423 fix: move user_tag variable declaration outside conditional block 2024-12-09 08:27:30 +02:00
e3d779c30d Fix typo model_weak 2024-12-08 22:09:48 +07:00
88a93bdcd7 Update weak model document 2024-12-08 22:01:00 +07:00
3c31048afc Update model in git provider 2024-12-08 22:00:37 +07:00
fc5dda0957 Use weak model for the rest flows 2024-12-08 21:51:29 +07:00
936894e4d1 Use regular model for pr review and code suggestion flows 2024-12-08 21:51:09 +07:00
dec2859fc4 Set default model to weak model 2024-12-08 21:10:26 +07:00
a4d9a65fc6 Add model_week 2024-12-08 20:23:36 +07:00
683108d3a5 Removed model_turbo 2024-12-08 20:10:38 +07:00
e68e100117 typo 2024-12-08 11:46:10 +02:00
Tal
158892047b Merge pull request #1386 from Codium-ai/tr/self_check
Tr/self check
2024-12-08 11:42:53 +02:00
Tal
7d5e59cd40 Update tests/health_test/main.py
Co-authored-by: qodo-merge-pro-for-open-source[bot] <189517486+qodo-merge-pro-for-open-source[bot]@users.noreply.github.com>
2024-12-08 11:41:05 +02:00
e8fc351ce9 docs: add CLI health check section and reorganize automations documentation 2024-12-08 11:39:15 +02:00
43e91b0df7 feat: add health test for PR agent commands and improve output handling 2024-12-08 11:27:43 +02:00
39a461b3b2 docs: update badges and clarify Qodo Merge Pro description 2024-12-05 21:50:39 +02:00
19ade4acf0 fixed link 2024-12-04 14:29:12 +02:00
Tal
10f8b522db Merge pull request #1381 from Codium-ai/tr/qodo_installation
Tr/qodo installation
2024-12-03 18:17:37 +02:00
d26ca4f71c docs: update Qodo Merge Pro installation documentation with Bitbucket support 2024-12-03 18:16:02 +02:00
9160f756db docs: update Qodo Merge Pro installation documentation with Bitbucket support 2024-12-03 18:14:36 +02:00
84c3a7b969 docs: update Qodo Merge Pro installation documentation with Bitbucket support 2024-12-03 18:12:21 +02:00
d9f9cc65b3 Merge pull request #1380 from Codium-ai/hl/ticket_docs_update
Update fetching_ticket_context.md
2024-12-03 18:04:06 +02:00
7d99c0db8e Merge remote-tracking branch 'origin/main' 2024-12-03 17:48:14 +02:00
fe20a8c5e7 docs: update Qodo Merge Pro installation documentation with rebranding changes 2024-12-03 17:48:05 +02:00
43c95106d4 Update fetching_ticket_context.md 2024-12-03 17:18:40 +02:00
Tal
1dd5f0b848 Merge pull request #1379 from Codium-ai/tr/disable_auto_commands
Add disable_auto_feedback configuration option to control automatic feedback
2024-12-02 21:34:15 +02:00
8610aa27a4 Add disable_auto_feedback configuration option to control automatic PR feedback 2024-12-02 21:28:48 +02:00
91bf3c0749 openai version 2024-12-02 09:23:51 +02:00
Tal
159155785e Update README.md 2024-12-02 08:46:36 +02:00
Tal
eabc296246 Merge pull request #1376 from pdecat/enhancement/generalize_publish_output_progress
Add publish_output_progress config support to AzureDevOps, BitBucket and Gitlab providers
2024-12-02 08:27:06 +02:00
Tal
b44030114e Merge pull request #1374 from KennyDizi/main
Add Support for GPT-4o November 2024 Model and Update Configurations
2024-12-02 08:23:26 +02:00
Tal
1d6f87be3b Merge pull request #1375 from Codium-ai/update-google-tag-manager
Update Google Tag Manager ID in custom analytics integration
2024-12-02 07:53:16 +02:00
Tal
a7c6fa7bd2 Merge pull request #1364 from ryanzll/main
Check git_provider and reference_link before using them in utils.py
2024-12-02 07:52:59 +02:00
a825aec5f3 Add publish_output_progress config support to AzureDevOps, BitBucket and Gitlab providers 2024-11-28 17:15:24 +01:00
4df097c228 Update Google Tag Manager ID in custom analytics integration 2024-11-25 15:07:28 +02:00
6871e1b27a docs: add section on customizing best practices label in improve.md 2024-11-24 17:37:35 +02:00
4afe05761d docs: add section on best practices for multiple languages in improve.md 2024-11-24 17:22:18 +02:00
7d1b6c2f0a Upgrade litellm to v1.52.12 to support model gpt-4o-2024-11-20 2024-11-21 22:12:01 +07:00
3547cf2057 Update model_turbo and fallback_models 2024-11-21 22:10:55 +07:00
f2043d639c Add support model gpt-4o-2024-11-20 2024-11-21 22:10:27 +07:00
Tal
6240de3898 Merge pull request #1373 from Codium-ai/tr/ado
Improve logging and error handling in Azure DevOps provider for code …
2024-11-21 13:41:22 +02:00
f08b20c667 Improve logging and error handling in Azure DevOps provider for code suggestions 2024-11-21 13:37:48 +02:00
Tal
e64b468556 Update azure.md 2024-11-21 09:24:45 +02:00
Tal
d48d14dac7 Merge pull request #1369 from Codium-ai/tr/committable_comments
Tr/committable comments
2024-11-20 17:49:08 +02:00
eb0c959ca9 Add validation for committable comments within PR hunks in GitHub provider 2024-11-20 17:28:13 +02:00
741a70ad9d Add detailed diff code generation for GitLab suggestions and improve comment formatting 2024-11-20 17:26:36 +02:00
22ee03981e Add diff code generation for Bitbucket code suggestions and improve logging 2024-11-20 17:25:10 +02:00
Tal
b1336e7d08 Merge pull request #1355 from Codium-ai/tr/3-way-prs
use a more modern package
2024-11-18 17:02:26 +02:00
Tal
751caca141 Merge pull request #1367 from Codium-ai/tr/focus_only_on_problems_enabled
Enable focus_only_on_problems mode by default in configuration and up…
2024-11-18 16:49:57 +02:00
612004727c true 2024-11-18 16:47:55 +02:00
577ee0241d Enable focus_only_on_problems mode by default in configuration and update README.md 2024-11-18 16:35:23 +02:00
a141ca133c Update utils.py
1. add missed emoji for "PR contains tests"
2. check git_provider and reference_link before using them
2024-11-16 09:32:05 +08:00
a14b6a580d Enable pre-commit workflow with manual dispatch trigger 2024-11-14 15:40:29 +02:00
Tal
cc5005c490 Merge pull request #1362 from samuele-ruffino96/docs/update-ci-pipeline-variable-note
docs: add note about $CI_SERVER_FQDN variable in GitLab CI/CD pipeline
2024-11-14 15:36:33 +02:00
3a5d0f54ce docs: add note about $CI_SERVER_FQDN variable in GitLab CI/CD pipeline
Clarified that the $CI_SERVER_FQDN variable was introduced in GitLab 16.10 and explained how to combine $CI_SERVER_HOST:$CI_SERVER_PORT to achieve the same result in earlier GitLab versions.
2024-11-14 12:57:44 +01:00
Tal
cd8ba4f59f Merge pull request #1359 from Codium-ai/tr/is_bot_user
Refactor `is_bot_user` function to improve actor type handling
2024-11-14 08:29:05 +02:00
fe27f96bf1 Improve robustness of sender_id extraction in Bitbucket app server by using safe dictionary access 2024-11-14 08:26:04 +02:00
2c3aa7b2dc Improve actor data extraction logic in Bitbucket app server 2024-11-14 08:23:38 +02:00
c934523f2d Refactor is_bot_user function to improve actor type handling and logging 2024-11-14 08:19:49 +02:00
2f4545dc15 Refactor byte decoding in Bitbucket server provider using decode_if_bytes function 2024-11-12 08:26:33 +02:00
cbd490b3d7 use a more modern version 2024-11-12 08:23:11 +02:00
Tal
b07f96d26a Merge pull request #1354 from Codium-ai/tr/3-way-prs
Tr/3 way prs
2024-11-12 08:17:41 +02:00
065777040f Improve PR file content retrieval and logging verbosity handling 2024-11-12 08:06:02 +02:00
9c82047dc3 Add validation for hunk lines matching original file content in git patch processing 2024-11-12 07:50:37 +02:00
Tal
e0c15409bb Merge pull request #1351 from Codium-ai/tr/fix_docs
Fixed mkdocs emoji configuration after pre-commit error
2024-11-08 10:49:41 +02:00
d956c72cb6 Disable pre-commit workflow and update mkdocs emoji configuration 2024-11-08 10:46:35 +02:00
Tal
dfb3d801cf Merge pull request #1316 from yu-iskw/introduce-pre-commit
Introduce pre-commit hooks and GitHub Actions
2024-11-08 09:58:59 +02:00
Tal
5c5a3e267c Merge branch 'main' into introduce-pre-commit 2024-11-08 09:54:21 +02:00
Tal
f9380c2440 Merge pull request #1350 from NxPKG/patch-1
Remove unused deployment_id variable.
2024-11-08 09:49:07 +02:00
Tal
e6a1f14c0e Merge pull request #1345 from KennyDizi/main
Add Claude 3.5 Haiku Model Support and Update Dependencies
2024-11-07 17:23:28 +02:00
6339845eb4 Remove unused deployment_id variable.
The deployment_id variable is assigned but never used in the function.
2024-11-07 14:24:35 +06:00
Tal
732cc18fd6 Merge pull request #1348 from Codium-ai/tr/focus_only_on_problems
Add focus_only_on_problems setting for targeted code suggestions
2024-11-07 09:09:03 +02:00
84d0f80c81 Add documentation for focus_only_on_problems setting in improve.md and README.md 2024-11-07 09:07:16 +02:00
ee26bf35c1 Add documentation for focus_only_on_problems setting in improve.md and README.md 2024-11-07 09:06:30 +02:00
7a5e9102fd Add documentation for focus_only_on_problems setting in improve.md and README.md 2024-11-07 08:59:10 +02:00
a8c97bfa73 Add documentation for focus_only_on_problems setting in improve.md and README.md 2024-11-07 08:30:18 +02:00
af653a048f Add support model bedrock/anthropic.claude-3-5-haiku-20241022-v1:0 2024-11-07 09:12:52 +07:00
d2663f959a Add focus_only_on_problems setting for targeted code suggestions 2024-11-06 21:22:58 +02:00
e650fe9ce9 Merge remote-tracking branch 'origin/main' 2024-11-06 12:20:41 +02:00
daeca42ae8 Update ticket analysis review setting key in compliance check function 2024-11-06 12:20:31 +02:00
04496f9b0e Update tiktoken to v0.8.0 2024-11-06 08:07:44 +07:00
0eacb3e35e Update openai to v1.54.1 2024-11-06 08:07:19 +07:00
c5ed2f040a Update litellm to v1..52.0 2024-11-06 07:56:30 +07:00
c394fc2767 Upgrade anthropic version to 0.39.0 2024-11-06 07:55:19 +07:00
157251493a Add support claude-3-5-haiku-20241022 model 2024-11-06 07:52:58 +07:00
Tal
4a982a849d Merge pull request #1343 from Codium-ai/mrT23-patch-5
Update automations_and_usage.md
2024-11-05 11:30:16 +02:00
Tal
6e3544f523 Update automations_and_usage.md 2024-11-05 11:27:38 +02:00
Tal
bf3ebbb95f Merge pull request #1342 from Codium-ai/hl/docs_tickets
update docs
2024-11-04 17:20:00 +02:00
eb44ecb1be update docs 2024-11-04 17:18:18 +02:00
Tal
45bae48701 Merge pull request #1341 from Codium-ai/hl/docs_tickets
Hl/docs tickets
2024-11-04 16:36:01 +02:00
b2181e4c79 typos 2024-11-04 16:35:21 +02:00
5939d3b17b readme 2024-11-04 16:32:53 +02:00
c1f4964a55 update review 2024-11-04 16:19:17 +02:00
022e407d84 add documentation for ticket integrations 2024-11-04 15:52:39 +02:00
Tal
93ba2d239a Merge pull request #1331 from miyagi-do/nocode_suggestions_config
Add configuration option to control publish of no code suggestions message
2024-11-04 07:50:57 +02:00
Tal
fa49dd5167 Merge branch 'main' into nocode_suggestions_config 2024-11-04 07:50:22 +02:00
Tal
16029e66ad Update README.md 2024-11-03 18:15:09 +02:00
Tal
7bd6713335 Merge pull request #1338 from Codium-ai/tr/no_line_numbers
Add support for processing diffs without line numbers in code suggest…
2024-11-03 18:13:12 +02:00
ef3241285d Add support for processing diffs without line numbers in code suggestions tool 2024-11-03 17:34:30 +02:00
Tal
d9ef26dc1c Merge pull request #1337 from Codium-ai/mrT23-patch-5
Update additional_configurations.md
2024-11-03 14:15:53 +02:00
Tal
02949b2b96 Update additional_configurations.md 2024-11-03 14:14:14 +02:00
443d06df06 Add configuration option to control publish of no code suggestions message 2024-11-01 15:38:16 -04:00
852bb371af Add pre-commit.yml
Signed-off-by: Yu Ishikawa <yu-iskw@users.noreply.github.com>
2024-10-30 10:00:59 +09:00
7c90e44656 Add pre-commit
Signed-off-by: Yu Ishikawa <yu-iskw@users.noreply.github.com>
2024-10-30 10:00:42 +09:00
81dea65856 Format files by pre-commit run -a
Signed-off-by: Yu Ishikawa <yu-iskw@users.noreply.github.com>
2024-10-30 10:00:36 +09:00
a3d572fb69 Add .pre-commit-config.yaml
Signed-off-by: Yu Ishikawa <yu-iskw@users.noreply.github.com>
2024-10-30 09:55:15 +09:00
173 changed files with 4681 additions and 2266 deletions

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

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

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

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

View File

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

View File

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

View File

@ -37,5 +37,3 @@ jobs:
name: Test dev docker name: Test dev docker
run: | run: |
docker run --rm codiumai/pr-agent:test pytest -v tests/unittest docker run --rm codiumai/pr-agent:test pytest -v tests/unittest

View File

@ -30,6 +30,3 @@ jobs:
GITHUB_ACTION_CONFIG.AUTO_DESCRIBE: true GITHUB_ACTION_CONFIG.AUTO_DESCRIBE: true
GITHUB_ACTION_CONFIG.AUTO_REVIEW: true GITHUB_ACTION_CONFIG.AUTO_REVIEW: true
GITHUB_ACTION_CONFIG.AUTO_IMPROVE: true GITHUB_ACTION_CONFIG.AUTO_IMPROVE: true

17
.github/workflows/pre-commit.yml vendored Normal file
View File

@ -0,0 +1,17 @@
# disabled. We might run it manually if needed.
name: pre-commit
on:
workflow_dispatch:
# 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

2
.gitignore vendored
View File

@ -1,6 +1,7 @@
.idea/ .idea/
.lsp/ .lsp/
.vscode/ .vscode/
.env
venv/ venv/
pr_agent/settings/.secrets.toml pr_agent/settings/.secrets.toml
__pycache__ __pycache__
@ -9,3 +10,4 @@ dist/
build/ build/
.DS_Store .DS_Store
docs/.cache/ docs/.cache/
.qodo

46
.pre-commit-config.yaml Normal file
View File

@ -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

45
CODE_OF_CONDUCT.md Normal file
View File

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

38
CONTRIBUTING.md Normal file
View File

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

View File

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

277
README.md
View File

@ -4,82 +4,91 @@
<picture> <picture>
<source media="(prefers-color-scheme: dark)" srcset="https://codium.ai/images/pr_agent/logo-dark.png" width="330"> <source media="(prefers-color-scheme: dark)" srcset="https://www.qodo.ai/wp-content/uploads/2025/02/PR-Agent-Purple-2.png">
<source media="(prefers-color-scheme: light)" srcset="https://codium.ai/images/pr_agent/logo-light.png" width="330"> <source media="(prefers-color-scheme: light)" srcset="https://www.qodo.ai/wp-content/uploads/2025/02/PR-Agent-Purple-2.png">
<img src="https://codium.ai/images/pr_agent/logo-light.png" alt="logo" width="330"> <img src="https://codium.ai/images/pr_agent/logo-light.png" alt="logo" width="330">
</picture> </picture>
<br/> <br/>
Qode Merge PR-Agent aims to help efficiently review and handle pull requests, by providing AI feedback and suggestions
[Installation Guide](https://qodo-merge-docs.qodo.ai/installation/) |
[Usage Guide](https://qodo-merge-docs.qodo.ai/usage-guide/) |
[Tools Guide](https://qodo-merge-docs.qodo.ai/tools/) |
[Qodo Merge](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/) 💎
PR-Agent aims to help efficiently review and handle pull requests, by providing AI feedback and suggestions
</div> </div>
[![GitHub license](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://github.com/Codium-ai/pr-agent/blob/main/LICENSE) [![Static Badge](https://img.shields.io/badge/Chrome-Extension-violet)](https://chromewebstore.google.com/detail/qodo-merge-ai-powered-cod/ephlnjeghhogofkifjloamocljapahnl)
[![Static Badge](https://img.shields.io/badge/Chrome-Extension-violet)](https://chromewebstore.google.com/detail/pr-agent-chrome-extension/ephlnjeghhogofkifjloamocljapahnl) [![Static Badge](https://img.shields.io/badge/Pro-App-blue)](https://github.com/apps/qodo-merge-pro/)
[![Static Badge](https://img.shields.io/badge/Code-Benchmark-blue)](https://pr-agent-docs.codium.ai/finetuning_benchmark/) [![Static Badge](https://img.shields.io/badge/OpenSource-App-red)](https://github.com/apps/qodo-merge-pro-for-open-source/)
[![Discord](https://badgen.net/badge/icon/discord?icon=discord&label&color=purple)](https://discord.com/channels/1057273017547378788/1126104260430528613) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label&color=purple)](https://discord.com/channels/1057273017547378788/1126104260430528613)
[![Twitter](https://img.shields.io/twitter/follow/codiumai)](https://twitter.com/codiumai) <a href="https://github.com/Codium-ai/pr-agent/commits/main">
[![Cheat Sheet](https://img.shields.io/badge/Cheat-Sheet-red)](https://www.codium.ai/images/pr_agent/cheat_sheet.pdf) <img alt="GitHub" src="https://img.shields.io/github/last-commit/Codium-ai/pr-agent/main?style=for-the-badge" height="20">
<a href="https://github.com/Codium-ai/pr-agent/commits/main"> </a>
<img alt="GitHub" src="https://img.shields.io/github/last-commit/Codium-ai/pr-agent/main?style=for-the-badge" height="20">
</a>
</div> </div>
### [Documentation](https://pr-agent-docs.codium.ai/) [//]: # (### [Documentation]&#40;https://qodo-merge-docs.qodo.ai/&#41;)
- See the [Installation Guide](https://qodo-merge-docs.qodo.ai/installation/) for instructions on installing Qode Merge PR-Agent on different platforms.
- See the [Usage Guide](https://qodo-merge-docs.qodo.ai/usage-guide/) for instructions on running Qode Merge PR-Agent tools via different interfaces, such as CLI, PR Comments, or by automatically triggering them when a new PR is opened. [//]: # ()
[//]: # (- See the [Installation Guide]&#40;https://qodo-merge-docs.qodo.ai/installation/&#41; for instructions on installing PR-Agent on different platforms.)
- See the [Tools Guide](https://qodo-merge-docs.qodo.ai/tools/) for a detailed description of the different tools, and the available configurations for each tool. [//]: # ()
[//]: # (- See the [Usage Guide]&#40;https://qodo-merge-docs.qodo.ai/usage-guide/&#41; for instructions on running PR-Agent tools via different interfaces, such as CLI, PR Comments, or by automatically triggering them when a new PR is opened.)
[//]: # ()
[//]: # (- See the [Tools Guide]&#40;https://qodo-merge-docs.qodo.ai/tools/&#41; for a detailed description of the different tools, and the available configurations for each tool.)
## Table of Contents ## Table of Contents
- [News and Updates](#news-and-updates) - [News and Updates](#news-and-updates)
- [Overview](#overview) - [Overview](#overview)
- [Example results](#example-results) - [Example results](#example-results)
- [Try it now](#try-it-now) - [Try it now](#try-it-now)
- [PR-Agent Pro 💎](https://pr-agent-docs.codium.ai/overview/pr_agent_pro/) - [Qodo Merge](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/)
- [How it works](#how-it-works) - [How it works](#how-it-works)
- [Why use PR-Agent?](#why-use-pr-agent) - [Why use PR-Agent?](#why-use-pr-agent)
## News and Updates ## News and Updates
### October 27, 2024 ### Feb 27, 2025
- Updated the default model to `o3-mini` for all tools. You can still use the `gpt-4o` as the default model by setting the `model` parameter in the configuration file.
- Important updates and bug fixes for Azure DevOps, see [here](https://github.com/qodo-ai/pr-agent/pull/1583)
- Added support for adjusting the [response language](https://qodo-merge-docs.qodo.ai/usage-guide/additional_configurations/#language-settings) of the PR-Agent tools.
Qodo Merge PR Agent will now automatically document accepted code suggestions in a dedicated wiki page (`.pr_agent_accepted_suggestions`), enabling users to track historical changes, assess the tool's effectiveness, and learn from previously implemented recommendations in the repository. ### Feb 6, 2025
New design for the `/improve` tool:
This dedicated wiki page will also serve as a foundation for future AI model improvements, allowing it to learn from historically implemented suggestions and generate more targeted, contextually relevant recommendations. <kbd><img src="https://github.com/user-attachments/assets/26506430-550e-469a-adaa-af0a09b70c6d" width="512"></kbd>
Read more about this novel feature [here](https://qodo-merge-docs.qodo.ai/tools/improve/#suggestion-tracking).
<kbd><img href="https://qodo.ai/images/pr_agent/pr_agent_accepted_suggestions1.png" src="https://qodo.ai/images/pr_agent/pr_agent_accepted_suggestions1.png" width="768"></kbd> ### Jan 25, 2025
The open-source GitHub organization was updated:
`https://github.com/codium-ai/pr-agent`
`https://github.com/qodo-ai/pr-agent`
The docker should be redirected automatically to the new location.
However, if you have any issues, please update the GitHub action docker image from
`uses: Codium-ai/pr-agent@main`
to
`uses: qodo-ai/pr-agent@main`
### Jan 2, 2025
### October 21, 2024 New tool [/Implement](https://qodo-merge-docs.qodo.ai/tools/implement/) (💎), which converts human code review discussions and feedback into ready-to-commit code changes.
**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`. <kbd><img src="https://www.qodo.ai/images/pr_agent/implement1.png?v=2" width="512"></kbd>
We constantly strive to balance informative AI analysis with reducing unnecessary noise. User feedback indicated that in many cases, the original PR title alone provides sufficient information, making the generated labels (`enhancement`, `documentation`, `bug fix`, ...) redundant.
The [`review_effort`](https://qodo-merge-docs.qodo.ai/tools/review/#configuration-options) label, generated by the `review` tool, will still be published by default, as it provides valuable information enabling reviewers to prioritize small PRs first.
However, every user has different preferences. To still publish the `describe` labels, set `pr_description.publish_labels=true` in the [configuration file](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/).
For more tailored and relevant labeling, we recommend using the [`custom_labels 💎`](https://qodo-merge-docs.qodo.ai/tools/custom_labels/) tool, that allows generating labels specific to your project's needs.
<kbd>![image](https://github.com/user-attachments/assets/8f38d222-53b1-4742-b2ec-7ea0a30c9076)</kbd>
<kbd>![image](https://github.com/user-attachments/assets/8285bd90-0dda-4c7e-9237-bbfde5e21880)</kbd>
### Jan 1, 2025
### October 14, 2024 Update logic and [documentation](https://qodo-merge-docs.qodo.ai/usage-guide/changing_a_model/#ollama) for running local models via Ollama.
Improved support for GitHub enterprise server with [GitHub Actions](https://qodo-merge-docs.qodo.ai/installation/github/#action-for-github-enterprise-server)
### October 10, 2024 ### December 30, 2024
New ability for the `review` tool - **ticket compliance feedback**. If the PR contains a ticket number, PR-Agent will check if the PR code actually [complies](https://github.com/Codium-ai/pr-agent/pull/1279#issuecomment-2404042130) with the ticket requirements.
<kbd><img src="https://github.com/user-attachments/assets/4a2a728b-5f47-40fa-80cc-16efd296938c" width="768"></kbd> Following feedback from the community, we have addressed two vulnerabilities identified in the open-source PR-Agent project. The [fixes](https://github.com/qodo-ai/pr-agent/pull/1425) are now included in the newly released version (v0.26), available as of today.
## Overview ## Overview
@ -87,69 +96,77 @@ New ability for the `review` tool - **ticket compliance feedback**. If the PR co
Supported commands per platform: Supported commands per platform:
| | | GitHub | Gitlab | Bitbucket | Azure DevOps | | | | GitHub | GitLab | Bitbucket | Azure DevOps |
|-------|---------------------------------------------------------------------------------------------------------|:--------------------:|:--------------------:|:--------------------:|:------------:| |-------|---------------------------------------------------------------------------------------------------------|:--------------------:|:--------------------:|:---------:|:------------:|
| TOOLS | Review | ✅ | ✅ | | ✅ | | TOOLS | [Review](https://qodo-merge-docs.qodo.ai/tools/review/) | ✅ | ✅ | | ✅ |
| | ⮑ Incremental | ✅ | | | | | | [Describe](https://qodo-merge-docs.qodo.ai/tools/describe/) | ✅ | ✅ | ✅ | |
| | Describe | ✅ | ✅ | | ✅ | | | [Improve](https://qodo-merge-docs.qodo.ai/tools/improve/) | ✅ | ✅ | | ✅ |
| | ⮑ [Inline File Summary](https://pr-agent-docs.codium.ai/tools/describe#inline-file-summary) 💎 | ✅ | | | | | | [Ask](https://qodo-merge-docs.qodo.ai/tools/ask/) | ✅ | ✅ | ✅ | ✅ |
| | Improve | ✅ | ✅ | ✅ | ✅ | | | ⮑ [Ask on code lines](https://qodo-merge-docs.qodo.ai/tools/ask/#ask-lines) | ✅ | ✅ | | |
| | ⮑ Extended | ✅ | ✅ | | ✅ | | | [Update CHANGELOG](https://qodo-merge-docs.qodo.ai/tools/update_changelog/) | ✅ | ✅ | | ✅ |
| | Ask | ✅ | ✅ | ✅ | ✅ | | | [Ticket Context](https://qodo-merge-docs.qodo.ai/core-abilities/fetching_ticket_context/) 💎 | ✅ | ✅ | ✅ | |
| | ⮑ [Ask on code lines](https://pr-agent-docs.codium.ai/tools/ask#ask-lines) | ✅ | ✅ | | | | | [Utilizing Best Practices](https://qodo-merge-docs.qodo.ai/tools/improve/#best-practices) 💎 | ✅ | ✅ | ✅ | |
| | [Custom Prompt](https://pr-agent-docs.codium.ai/tools/custom_prompt/) 💎 | ✅ | ✅ | ✅ | | | | [PR Chat](https://qodo-merge-docs.qodo.ai/chrome-extension/features/#pr-chat) 💎 | ✅ | | | |
| | [Test](https://pr-agent-docs.codium.ai/tools/test/) 💎 | ✅ | ✅ | | | | | [Suggestion Tracking](https://qodo-merge-docs.qodo.ai/tools/improve/#suggestion-tracking) 💎 | ✅ | ✅ | | |
| | Reflect and Review | ✅ | ✅ | ✅ | | | | [CI Feedback](https://qodo-merge-docs.qodo.ai/tools/ci_feedback/) 💎 | ✅ | | | |
| | Update CHANGELOG.md | ✅ | ✅ | ✅ | ✅ | | | [PR Documentation](https://qodo-merge-docs.qodo.ai/tools/documentation/) 💎 | ✅ | ✅ | | |
| | Find Similar Issue | ✅ | | | | | | [Custom Labels](https://qodo-merge-docs.qodo.ai/tools/custom_labels/) 💎 | ✅ | ✅ | | |
| | [Add PR Documentation](https://pr-agent-docs.codium.ai/tools/documentation/) 💎 | ✅ | ✅ | | | | | [Analyze](https://qodo-merge-docs.qodo.ai/tools/analyze/) 💎 | ✅ | ✅ | | |
| | [Custom Labels](https://pr-agent-docs.codium.ai/tools/custom_labels/) 💎 | ✅ | ✅ | | | | | [Similar Code](https://qodo-merge-docs.qodo.ai/tools/similar_code/) 💎 | ✅ | | | |
| | [Analyze](https://pr-agent-docs.codium.ai/tools/analyze/) 💎 | ✅ | ✅ | | | | | [Custom Prompt](https://qodo-merge-docs.qodo.ai/tools/custom_prompt/) 💎 | ✅ | ✅ | | |
| | [CI Feedback](https://pr-agent-docs.codium.ai/tools/ci_feedback/) 💎 | ✅ | | | | | | [Test](https://qodo-merge-docs.qodo.ai/tools/test/) 💎 | ✅ | ✅ | | |
| | [Similar Code](https://pr-agent-docs.codium.ai/tools/similar_code/) 💎 | ✅ | | | | | | [Implement](https://qodo-merge-docs.qodo.ai/tools/implement/) 💎 | ✅ | ✅ | ✅ | |
| | [Auto-Approve](https://qodo-merge-docs.qodo.ai/tools/improve/?h=auto#auto-approval) 💎 | ✅ | ✅ | ✅ | |
| | | | | | | | | | | | | |
| USAGE | CLI | ✅ | ✅ | | ✅ | | USAGE | [CLI](https://qodo-merge-docs.qodo.ai/usage-guide/automations_and_usage/#local-repo-cli) | ✅ | ✅ | | ✅ |
| | App / webhook | ✅ | ✅ | | ✅ | | | [App / webhook](https://qodo-merge-docs.qodo.ai/usage-guide/automations_and_usage/#github-app) | ✅ | ✅ | | ✅ |
| | Tagging bot | ✅ | | | | | | [Tagging bot](https://github.com/Codium-ai/pr-agent#try-it-now) | ✅ | | | |
| | Actions | ✅ |✅| |✅| | | [Actions](https://qodo-merge-docs.qodo.ai/installation/github/#run-as-a-github-action) | ✅ |✅| |✅|
| | | | | | | | | | | | | |
| CORE | PR compression | ✅ | ✅ | | ✅ | | CORE | [PR compression](https://qodo-merge-docs.qodo.ai/core-abilities/compression_strategy/) | ✅ | ✅ | | ✅ |
| | Repo language prioritization | ✅ | ✅ | ✅ | ✅ |
| | Adaptive and token-aware file patch fitting | ✅ | ✅ | ✅ | ✅ | | | Adaptive and token-aware file patch fitting | ✅ | ✅ | ✅ | ✅ |
| | Multiple models support | ✅ | ✅ | | ✅ | | | [Multiple models support](https://qodo-merge-docs.qodo.ai/usage-guide/changing_a_model/) | ✅ | ✅ | | ✅ |
| | [Static code analysis](https://pr-agent-docs.codium.ai/core-abilities/#static-code-analysis) 💎 | ✅ | ✅ | | | | | [Local and global metadata](https://qodo-merge-docs.qodo.ai/core-abilities/metadata/) | ✅ | ✅ | | |
| | [Global and wiki configurations](https://pr-agent-docs.codium.ai/usage-guide/configuration_options/) 💎 | ✅ | ✅ | | | | | [Dynamic context](https://qodo-merge-docs.qodo.ai/core-abilities/dynamic_context/) | ✅ | ✅ | | |
| | [PR interactive actions](https://www.codium.ai/images/pr_agent/pr-actions.mp4) 💎 | ✅ | ✅ | | | | | [Self reflection](https://qodo-merge-docs.qodo.ai/core-abilities/self_reflection/) | ✅ | ✅ | ✅ | |
- 💎 means this feature is available only in [PR-Agent Pro](https://www.codium.ai/pricing/) | | [Static code analysis](https://qodo-merge-docs.qodo.ai/core-abilities/static_code_analysis/) 💎 | ✅ | ✅ | | |
| | [Global and wiki configurations](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/) 💎 | ✅ | ✅ | ✅ | |
| | [PR interactive actions](https://www.qodo.ai/images/pr_agent/pr-actions.mp4) 💎 | ✅ | ✅ | | |
| | [Impact Evaluation](https://qodo-merge-docs.qodo.ai/core-abilities/impact_evaluation/) 💎 | ✅ | ✅ | | |
- 💎 means this feature is available only in [Qodo-Merge](https://www.qodo.ai/pricing/)
[//]: # (- Support for additional git providers is described in [here]&#40;./docs/Full_environments.md&#41;) [//]: # (- Support for additional git providers is described in [here]&#40;./docs/Full_environments.md&#41;)
___ ___
**Auto Description ([`/describe`](https://pr-agent-docs.codium.ai/tools/describe/))**: Automatically generating PR description - title, type, summary, code walkthrough and labels. **Auto Description ([`/describe`](https://qodo-merge-docs.qodo.ai/tools/describe/))**: Automatically generating PR description - title, type, summary, code walkthrough and labels.
\ \
**Auto Review ([`/review`](https://pr-agent-docs.codium.ai/tools/review/))**: Adjustable feedback about the PR, possible issues, security concerns, review effort and more. **Auto Review ([`/review`](https://qodo-merge-docs.qodo.ai/tools/review/))**: Adjustable feedback about the PR, possible issues, security concerns, review effort and more.
\ \
**Code Suggestions ([`/improve`](https://pr-agent-docs.codium.ai/tools/improve/))**: Code suggestions for improving the PR. **Code Suggestions ([`/improve`](https://qodo-merge-docs.qodo.ai/tools/improve/))**: Code suggestions for improving the PR.
\ \
**Question Answering ([`/ask ...`](https://pr-agent-docs.codium.ai/tools/ask/))**: Answering free-text questions about the PR. **Question Answering ([`/ask ...`](https://qodo-merge-docs.qodo.ai/tools/ask/))**: Answering free-text questions about the PR.
\ \
**Update Changelog ([`/update_changelog`](https://pr-agent-docs.codium.ai/tools/update_changelog/))**: Automatically updating the CHANGELOG.md file with the PR changes. **Update Changelog ([`/update_changelog`](https://qodo-merge-docs.qodo.ai/tools/update_changelog/))**: Automatically updating the CHANGELOG.md file with the PR changes.
\ \
**Find Similar Issue ([`/similar_issue`](https://pr-agent-docs.codium.ai/tools/similar_issues/))**: Automatically retrieves and presents similar issues. **Find Similar Issue ([`/similar_issue`](https://qodo-merge-docs.qodo.ai/tools/similar_issues/))**: Automatically retrieves and presents similar issues.
\ \
**Add Documentation 💎 ([`/add_docs`](https://pr-agent-docs.codium.ai/tools/documentation/))**: Generates documentation to methods/functions/classes that changed in the PR. **Add Documentation 💎 ([`/add_docs`](https://qodo-merge-docs.qodo.ai/tools/documentation/))**: Generates documentation to methods/functions/classes that changed in the PR.
\ \
**Generate Custom Labels 💎 ([`/generate_labels`](https://pr-agent-docs.codium.ai/tools/custom_labels/))**: Generates custom labels for the PR, based on specific guidelines defined by the user. **Generate Custom Labels 💎 ([`/generate_labels`](https://qodo-merge-docs.qodo.ai/tools/custom_labels/))**: Generates custom labels for the PR, based on specific guidelines defined by the user.
\ \
**Analyze 💎 ([`/analyze`](https://pr-agent-docs.codium.ai/tools/analyze/))**: Identify code components that changed in the PR, and enables to interactively generate tests, docs, and code suggestions for each component. **Analyze 💎 ([`/analyze`](https://qodo-merge-docs.qodo.ai/tools/analyze/))**: Identify code components that changed in the PR, and enables to interactively generate tests, docs, and code suggestions for each component.
\ \
**Custom Prompt 💎 ([`/custom_prompt`](https://pr-agent-docs.codium.ai/tools/custom_prompt/))**: Automatically generates custom suggestions for improving the PR code, based on specific guidelines defined by the user. **Test 💎 ([`/test`](https://qodo-merge-docs.qodo.ai/tools/test/))**: Generate tests for a selected component, based on the PR code changes.
\ \
**Generate Tests 💎 ([`/test component_name`](https://pr-agent-docs.codium.ai/tools/test/))**: Generates unit tests for a selected component, based on the PR code changes. **Custom Prompt 💎 ([`/custom_prompt`](https://qodo-merge-docs.qodo.ai/tools/custom_prompt/))**: Automatically generates custom suggestions for improving the PR code, based on specific guidelines defined by the user.
\ \
**CI Feedback 💎 ([`/checks ci_job`](https://pr-agent-docs.codium.ai/tools/ci_feedback/))**: Automatically generates feedback and analysis for a failed CI job. **Generate Tests 💎 ([`/test component_name`](https://qodo-merge-docs.qodo.ai/tools/test/))**: Generates unit tests for a selected component, based on the PR code changes.
\ \
**Similar Code 💎 ([`/find_similar_component`](https://pr-agent-docs.codium.ai/tools/similar_code/))**: Retrieves the most similar code components from inside the organization's codebase, or from open-source code. **CI Feedback 💎 ([`/checks ci_job`](https://qodo-merge-docs.qodo.ai/tools/ci_feedback/))**: Automatically generates feedback and analysis for a failed CI job.
\
**Similar Code 💎 ([`/find_similar_component`](https://qodo-merge-docs.qodo.ai/tools/similar_code/))**: Retrieves the most similar code components from inside the organization's codebase, or from open-source code.
\
**Implement 💎 ([`/implement`](https://qodo-merge-docs.qodo.ai/tools/implement/))**: Generates implementation code from review suggestions.
___ ___
## Example results ## Example results
@ -180,50 +197,8 @@ ___
</kbd> </kbd>
</p> </p>
</div> </div>
<hr>
<h4><a href="https://github.com/Codium-ai/pr-agent/pull/530">/generate_labels</a></h4>
<div align="center">
<p float="center">
<kbd><img src="https://www.codium.ai/images/pr_agent/geneare_custom_labels_main_short.png" width="300"></kbd>
</p>
</div>
[//]: # (<h4><a href="https://github.com/Codium-ai/pr-agent/pull/78#issuecomment-1639739496">/reflect_and_review:</a></h4>)
[//]: # (<div align="center">)
[//]: # (<p float="center">)
[//]: # (<img src="https://www.codium.ai/images/reflect_and_review.gif" width="800">)
[//]: # (</p>)
[//]: # (</div>)
[//]: # (<h4><a href="https://github.com/Codium-ai/pr-agent/pull/229#issuecomment-1695020538">/ask:</a></h4>)
[//]: # (<div align="center">)
[//]: # (<p float="center">)
[//]: # (<img src="https://www.codium.ai/images/ask-2.gif" width="800">)
[//]: # (</p>)
[//]: # (</div>)
[//]: # (<h4><a href="https://github.com/Codium-ai/pr-agent/pull/229#issuecomment-1695024952">/improve:</a></h4>)
[//]: # (<div align="center">)
[//]: # (<p float="center">)
[//]: # (<img src="https://www.codium.ai/images/improve-2.gif" width="800">)
[//]: # (</p>)
[//]: # (</div>)
<div align="left"> <div align="left">
@ -244,22 +219,16 @@ Note that this is a promotional bot, suitable only for initial experimentation.
It does not have 'edit' access to your repo, for example, so it cannot update the PR description or add labels (`@CodiumAI-Agent /describe` will publish PR description as a comment). In addition, the bot cannot be used on private repositories, as it does not have access to the files there. It does not have 'edit' access to your repo, for example, so it cannot update the PR description or add labels (`@CodiumAI-Agent /describe` will publish PR description as a comment). In addition, the bot cannot be used on private repositories, as it does not have access to the files there.
![Review generation process](https://www.codium.ai/images/demo-2.gif)
To set up your own PR-Agent, see the [Installation](https://pr-agent-docs.codium.ai/installation/) section below.
Note that when you set your own PR-Agent or use CodiumAI hosted PR-Agent, there is no need to mention `@CodiumAI-Agent ...`. Instead, directly start with the command, e.g., `/ask ...`.
--- ---
## PR-Agent Pro 💎 ## Qodo Merge 💎
[PR-Agent Pro](https://www.codium.ai/pricing/) is a hosted version of PR-Agent, provided by CodiumAI. It is available for a monthly fee, and provides the following benefits: [Qodo Merge](https://www.qodo.ai/pricing/) is a hosted version of PR-Agent, provided by Qodo. It is available for a monthly fee, and provides the following benefits:
1. **Fully managed** - We take care of everything for you - hosting, models, regular updates, and more. Installation is as simple as signing up and adding the PR-Agent app to your GitHub\GitLab\BitBucket repo. 1. **Fully managed** - We take care of everything for you - hosting, models, regular updates, and more. Installation is as simple as signing up and adding the Qodo Merge app to your GitHub\GitLab\BitBucket repo.
2. **Improved privacy** - No data will be stored or used to train models. PR-Agent Pro will employ zero data retention, and will use an OpenAI account with zero data retention. 2. **Improved privacy** - No data will be stored or used to train models. Qodo Merge will employ zero data retention, and will use an OpenAI account with zero data retention.
3. **Improved support** - PR-Agent Pro users will receive priority support, and will be able to request new features and capabilities. 3. **Improved support** - Qodo Merge 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, Qodo Merge 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. See [here](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/) for a list of features available in Qodo Merge.
@ -267,9 +236,9 @@ See [here](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/) for a list of
The following diagram illustrates PR-Agent tools and their flow: The following diagram illustrates PR-Agent tools and their flow:
![PR-Agent Tools](https://codium.ai/images/pr_agent/diagram-v0.9.png) ![PR-Agent Tools](https://www.qodo.ai/images/pr_agent/diagram-v0.9.png)
Check out the [PR Compression strategy](https://pr-agent-docs.codium.ai/core-abilities/#pr-compression-strategy) page for more details on how we convert a code diff to a manageable LLM prompt Check out the [PR Compression strategy](https://qodo-merge-docs.qodo.ai/core-abilities/#pr-compression-strategy) page for more details on how we convert a code diff to a manageable LLM prompt
## Why use PR-Agent? ## Why use PR-Agent?
@ -278,7 +247,7 @@ A reasonable question that can be asked is: `"Why use PR-Agent? What makes it st
Here are some advantages of PR-Agent: Here are some advantages of PR-Agent:
- We emphasize **real-life practical usage**. Each tool (review, improve, ask, ...) has a single GPT-4 call, no more. We feel that this is critical for realistic team usage - obtaining an answer quickly (~30 seconds) and affordably. - We emphasize **real-life practical usage**. Each tool (review, improve, ask, ...) has a single GPT-4 call, no more. We feel that this is critical for realistic team usage - obtaining an answer quickly (~30 seconds) and affordably.
- Our [PR Compression strategy](https://pr-agent-docs.codium.ai/core-abilities/#pr-compression-strategy) is a core ability that enables to effectively tackle both short and long PRs. - Our [PR Compression strategy](https://qodo-merge-docs.qodo.ai/core-abilities/#pr-compression-strategy) is a core ability that enables to effectively tackle both short and long PRs.
- Our JSON prompting strategy enables to have **modular, customizable tools**. For example, the '/review' tool categories can be controlled via the [configuration](pr_agent/settings/configuration.toml) file. Adding additional categories is easy and accessible. - Our JSON prompting strategy enables to have **modular, customizable tools**. For example, the '/review' tool categories can be controlled via the [configuration](pr_agent/settings/configuration.toml) file. Adding additional categories is easy and accessible.
- We support **multiple git providers** (GitHub, Gitlab, Bitbucket), **multiple ways** to use the tool (CLI, GitHub Action, GitHub App, Docker, ...), and **multiple models** (GPT-4, GPT-3.5, Anthropic, Cohere, Llama2). - We support **multiple git providers** (GitHub, Gitlab, Bitbucket), **multiple ways** to use the tool (CLI, GitHub Action, GitHub App, Docker, ...), and **multiple models** (GPT-4, GPT-3.5, Anthropic, Cohere, Llama2).
@ -290,24 +259,22 @@ Here are some advantages of PR-Agent:
- If you host PR-Agent with your OpenAI API key, it is between you and OpenAI. You can read their API data privacy policy here: - If you host PR-Agent with your OpenAI API key, it is between you and OpenAI. You can read their API data privacy policy here:
https://openai.com/enterprise-privacy https://openai.com/enterprise-privacy
### CodiumAI-hosted PR-Agent Pro 💎 ### Qodo-hosted Qodo Merge 💎
- When using PR-Agent Pro 💎, hosted by CodiumAI, we will not store any of your data, nor will we use it for training. You will also benefit from an OpenAI account with zero data retention. - When using Qodo Merge 💎, hosted by Qodo, we will not store any of your data, nor will we use it for training. You will also benefit from an OpenAI account with zero data retention.
- For certain clients, CodiumAI-hosted PR-Agent Pro will use CodiumAIs proprietary models — if this is the case, you will be notified. - For certain clients, Qodo-hosted Qodo Merge will use Qodos proprietary models — if this is the case, you will be notified.
- No passive collection of Code and Pull Requests data — PR-Agent will be active only when you invoke it, and it will then extract and analyze only data relevant to the executed command and queried pull request. - No passive collection of Code and Pull Requests data — Qodo Merge will be active only when you invoke it, and it will then extract and analyze only data relevant to the executed command and queried pull request.
### PR-Agent Chrome extension ### Qodo Merge Chrome extension
- The [PR-Agent Chrome extension](https://chromewebstore.google.com/detail/pr-agent-chrome-extension/ephlnjeghhogofkifjloamocljapahnl) serves solely to modify the visual appearance of a GitHub PR screen. It does not transmit any user's repo or pull request code. Code is only sent for processing when a user submits a GitHub comment that activates a PR-Agent tool, in accordance with the standard privacy policy of PR-Agent. - The [Qodo Merge Chrome extension](https://chromewebstore.google.com/detail/qodo-merge-ai-powered-cod/ephlnjeghhogofkifjloamocljapahnl) serves solely to modify the visual appearance of a GitHub PR screen. It does not transmit any user's repo or pull request code. Code is only sent for processing when a user submits a GitHub comment that activates a PR-Agent tool, in accordance with the standard privacy policy of Qodo-Merge.
## Links ## Links
[![Join our Discord community](https://raw.githubusercontent.com/Codium-ai/codiumai-vscode-release/main/media/docs/Joincommunity.png)](https://discord.gg/kG35uSHDBc)
- Discord community: https://discord.gg/kG35uSHDBc - Discord community: https://discord.gg/kG35uSHDBc
- CodiumAI site: https://codium.ai - Qodo site: https://www.qodo.ai/
- Blog: https://www.codium.ai/blog/ - Blog: https://www.qodo.ai/blog/
- Troubleshooting: https://www.codium.ai/blog/technical-faq-and-troubleshooting/ - Troubleshooting: https://www.qodo.ai/blog/technical-faq-and-troubleshooting/
- Support: support@codium.ai - Support: support@qodo.ai

62
SECURITY.md Normal file
View File

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

View File

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

View File

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

View File

@ -0,0 +1,315 @@
<div class="search-section">
<h1>AI Docs Search</h1>
<p class="search-description">
Search through our documentation using AI-powered natural language queries.
</p>
<div class="search-container">
<input
type="text"
id="searchInput"
class="search-input"
placeholder="Enter your search term..."
>
<button id="searchButton" class="search-button">Search</button>
</div>
<div id="spinner" class="spinner-container" style="display: none;">
<div class="spinner"></div>
</div>
<div id="results" class="results-container"></div>
</div>
<style>
Untitled
.search-section {
max-width: 800px;
margin: 0 auto;
padding: 0 1rem 2rem;
}
h1 {
color: #666;
font-size: 2.125rem;
font-weight: normal;
margin-bottom: 1rem;
}
.search-description {
color: #666;
font-size: 1rem;
line-height: 1.5;
margin-bottom: 2rem;
max-width: 800px;
}
.search-container {
display: flex;
gap: 1rem;
max-width: 800px;
margin: 0; /* Changed from auto to 0 to align left */
}
.search-input {
flex: 1;
padding: 0 0.875rem;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 0.9375rem;
outline: none;
height: 40px; /* Explicit height */
}
.search-input:focus {
border-color: #6c63ff;
}
.search-button {
padding: 0 1.25rem;
background-color: #2196F3;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 0.875rem;
transition: background-color 0.2s;
height: 40px; /* Match the height of search input */
display: flex;
align-items: center;
justify-content: center;
}
.search-button:hover {
background-color: #1976D2;
}
.spinner-container {
display: flex;
justify-content: center;
margin-top: 2rem;
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #2196F3;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.results-container {
margin-top: 2rem;
max-width: 800px;
}
.result-item {
padding: 1rem;
border: 1px solid #ddd;
border-radius: 4px;
margin-bottom: 1rem;
}
.result-title {
font-size: 1.2rem;
color: #2196F3;
margin-bottom: 0.5rem;
}
.result-description {
color: #666;
}
.error-message {
color: #dc3545;
padding: 1rem;
border: 1px solid #dc3545;
border-radius: 4px;
margin-top: 1rem;
}
.markdown-content {
line-height: 1.6;
color: var(--md-typeset-color);
background: var(--md-default-bg-color);
border: 1px solid var(--md-default-fg-color--lightest);
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
position: relative;
margin-top: 2rem;
}
.markdown-content::before {
content: '';
position: absolute;
top: -8px;
left: 24px;
width: 16px;
height: 16px;
background: var(--md-default-bg-color);
border-left: 1px solid var(--md-default-fg-color--lightest);
border-top: 1px solid var(--md-default-fg-color--lightest);
transform: rotate(45deg);
}
.markdown-content > *:first-child {
margin-top: 0;
padding-top: 0;
}
.markdown-content p {
margin-bottom: 1rem;
}
.markdown-content p:last-child {
margin-bottom: 0;
}
.markdown-content code {
background: var(--md-code-bg-color);
color: var(--md-code-fg-color);
padding: 0.2em 0.4em;
border-radius: 3px;
font-size: 0.9em;
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
}
.markdown-content pre {
background: var(--md-code-bg-color);
padding: 1rem;
border-radius: 6px;
overflow-x: auto;
margin: 1rem 0;
}
.markdown-content pre code {
background: none;
padding: 0;
font-size: 0.9em;
}
[data-md-color-scheme="slate"] .markdown-content {
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/9.1.6/marked.min.js"></script>
<script>
window.addEventListener('load', function() {
function displayResults(responseText) {
const resultsContainer = document.getElementById('results');
const spinner = document.getElementById('spinner');
const searchContainer = document.querySelector('.search-container');
// Hide spinner
spinner.style.display = 'none';
// Scroll to search bar
searchContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
try {
const results = JSON.parse(responseText);
marked.setOptions({
breaks: true,
gfm: true,
headerIds: false,
sanitize: false
});
const htmlContent = marked.parse(results.message);
resultsContainer.className = 'markdown-content';
resultsContainer.innerHTML = htmlContent;
// Scroll after content is rendered
setTimeout(() => {
const searchContainer = document.querySelector('.search-container');
const offset = 55; // Offset from top in pixels
const elementPosition = searchContainer.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.pageYOffset - offset;
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
});
}, 100);
} catch (error) {
console.error('Error parsing results:', error);
resultsContainer.innerHTML = '<div class="error-message">Error processing results</div>';
}
}
async function performSearch() {
const searchInput = document.getElementById('searchInput');
const resultsContainer = document.getElementById('results');
const spinner = document.getElementById('spinner');
const searchTerm = searchInput.value.trim();
if (!searchTerm) {
resultsContainer.innerHTML = '<div class="error-message">Please enter a search term</div>';
return;
}
// Show spinner, clear results
spinner.style.display = 'flex';
resultsContainer.innerHTML = '';
try {
const data = {
"query": searchTerm
};
const options = {
method: 'POST',
headers: {
'accept': 'text/plain',
'content-type': 'application/json',
},
body: JSON.stringify(data)
};
// const API_ENDPOINT = 'http://0.0.0.0:3000/api/v1/docs_help';
const API_ENDPOINT = 'https://help.merge.qodo.ai/api/v1/docs_help';
const response = await fetch(API_ENDPOINT, options);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const responseText = await response.text();
displayResults(responseText);
} catch (error) {
spinner.style.display = 'none';
resultsContainer.innerHTML = `
<div class="error-message">
An error occurred while searching. Please try again later.
</div>
`;
}
}
// Add event listeners
const searchButton = document.getElementById('searchButton');
const searchInput = document.getElementById('searchInput');
if (searchButton) {
searchButton.addEventListener('click', performSearch);
}
if (searchInput) {
searchInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
performSearch();
}
});
}
});
</script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 KiB

After

Width:  |  Height:  |  Size: 57 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,5 +1,4 @@
We take your code's security and privacy seriously: We take your code's security and privacy seriously:
- The Chrome extension will not send your code to any external servers. - 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. - For private repositories, we will first validate the user's identity and permissions. After authentication, we generate responses using the existing Qodo Merge integration.

View File

@ -8,7 +8,7 @@ To enable private chat, simply install the Qodo Merge Chrome extension. After in
This chat session is **private**, and won't be visible to other users. This chat session is **private**, and won't be visible to other users.
All open-source repositories are supported. All open-source repositories are supported.
For private repositories, you will also need to install Qodo Merge Pro, After installation, make sure to open at least one new PR to fully register your organization. Once done, you can chat with both new and existing PRs across all installed repositories. For private repositories, you will also need to install Qodo Merge. After installation, make sure to open at least one new PR to fully register your organization. Once done, you can chat with both new and existing PRs across all installed repositories.
#### Context-aware PR chat #### Context-aware PR chat

View File

@ -1,11 +1,11 @@
[Qodo Merge Chrome extension](https://chromewebstore.google.com/detail/pr-agent-chrome-extension/ephlnjeghhogofkifjloamocljapahnl) is a collection of tools that integrates seamlessly with your GitHub environment, aiming to enhance your Git usage experience, and providing AI-powered capabilities to your PRs. [Qodo Merge Chrome extension](https://chromewebstore.google.com/detail/pr-agent-chrome-extension/ephlnjeghhogofkifjloamocljapahnl){:target="_blank"} is a collection of tools that integrates seamlessly with your GitHub environment, aiming to enhance your Git usage experience, and providing AI-powered capabilities to your PRs.
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. 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 private repositories, you will need to install [Qodo Merge](https://github.com/apps/qodo-merge-pro){:target="_blank"} 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). For a demonstration of how to install Qodo Merge 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){:target="_blank"}.
<img src="https://codium.ai/images/pr_agent/PR-AgentChat.gif" width="768"> <img src="https://codium.ai/images/pr_agent/PR-AgentChat.gif" width="768">

View File

@ -0,0 +1,69 @@
# Auto Best Practices 💎
`Supported Git Platforms: GitHub`
## Overview
![Auto best practice suggestion graph](https://www.qodo.ai/images/pr_agent/auto_best_practices_graph.png){width=684}
> Note - enabling a [Wiki](https://qodo-merge-docs.qodo.ai/usage-guide/enabling_a_wiki/) is required for this feature.
### Finding Code Problems - Exploration Phase
The `improve` tool identifies potential issues, problems and bugs in Pull Request (PR) code changes.
Rather than focusing on minor issues like code style or formatting, the tool intelligently analyzes code to detect meaningful problems.
The analysis intentionally takes a flexible, _exploratory_ approach to identify meaningful potential issues, allowing the tool to surface relevant code suggestions without being constrained by predefined categories.
### Tracking Implemented Suggestions
Qodo Merge features a novel [tracking system](https://qodo-merge-docs.qodo.ai/tools/improve/#suggestion-tracking) that automatically detects when PR authors implement AI-generated code suggestions.
All accepted suggestions are aggregated in a repository-specific wiki page called [`.pr_agent_accepted_suggestions`](https://github.com/qodo-ai/pr-agent/wiki/.pr_agent_accepted_suggestions)
### Learning and Applying Auto Best Practices
Monthly, Qodo Merge analyzes the collection of accepted suggestions to generate repository-specific best practices, stored in [`.pr_agent_auto_best_practices`](https://github.com/qodo-ai/pr-agent/wiki/.pr_agent_auto_best_practices) wiki file.
These best practices reflect recurring patterns in accepted code improvements.
The `improve` tool will incorporate these best practices as an additional analysis layer, checking PR code changes against known patterns of previously accepted improvements.
This creates a two-phase analysis:
1. Open exploration for general code issues
2. Targeted checking against established best practices - exploiting the knowledge gained from past suggestions
By keeping these phases decoupled, the tool remains free to discover new or unseen issues and problems, while also learning from past experiences.
When presenting the suggestions generated by the `improve` tool, Qodo Merge will add a dedicated label for each suggestion generated from the auto best practices - 'Learned best practice':
![Auto best practice suggestion](https://www.qodo.ai/images/pr_agent/auto_best_practices.png){width=684}
## Auto Best Practices vs Custom Best Practices
Teams and companies can also manually define their own [custom best practices](https://qodo-merge-docs.qodo.ai/tools/improve/#best-practices) in Qodo Merge.
When custom best practices exist, Qodo Merge will still generate an 'auto best practices' wiki file, though it won't be used by the `improve` tool.
However, this auto-generated file can still serve two valuable purposes:
1. It can help enhance your custom best practices with additional insights derived from suggestions your team found valuable enough to implement
2. It demonstrates effective patterns for writing AI-friendly best practices
Even when using custom best practices, we recommend regularly reviewing the auto best practices file to refine your custom rules.
## Relevant configurations
```toml
[auto_best_practices]
# Disable all auto best practices usage or generation
enable_auto_best_practices = true
# Disable usage of auto best practices file in the 'improve' tool
utilize_auto_best_practices = true
# Extra instructions to the auto best practices generation prompt
extra_instructions = ""
# Max number of patterns to be detected
max_patterns = 5
```

View File

@ -0,0 +1,170 @@
# Fetching Ticket Context for PRs
`Supported Git Platforms: GitHub, GitLab, Bitbucket`
## Overview
Qodo Merge PR Agent streamlines code review workflows by seamlessly connecting with multiple ticket management systems.
This integration enriches the review process by automatically surfacing relevant ticket information and context alongside code changes.
## Ticket systems supported
- GitHub
- Jira (💎)
Ticket data fetched:
1. Ticket Title
2. Ticket Description
3. Custom Fields (Acceptance criteria)
4. Subtasks (linked tasks)
5. Labels
6. Attached Images/Screenshots
## Affected Tools
Ticket Recognition Requirements:
- The PR description should contain a link to the ticket or if the branch name starts with the ticket id / number.
- For Jira tickets, you should follow the instructions in [Jira Integration](https://qodo-merge-docs.qodo.ai/core-abilities/fetching_ticket_context/#jira-integration) in order to authenticate with Jira.
### Describe tool
Qodo Merge PR Agent will recognize the ticket and use the ticket content (title, description, labels) to provide additional context for the code changes.
By understanding the reasoning and intent behind modifications, the LLM can offer more insightful and relevant code analysis.
### Review tool
Similarly to the `describe` tool, the `review` tool will use the ticket content to provide additional context for the code changes.
In addition, this feature will evaluate how well a Pull Request (PR) adheres to its original purpose/intent as defined by the associated ticket or issue mentioned in the PR description.
Each ticket will be assigned a label (Compliance/Alignment level), Indicates the degree to which the PR fulfills its original purpose, Options: Fully compliant, Partially compliant or Not compliant.
![Ticket Compliance](https://www.qodo.ai/images/pr_agent/ticket_compliance_review.png){width=768}
By default, the tool will automatically validate if the PR complies with the referenced ticket.
If you want to disable this feedback, add the following line to your configuration file:
```toml
[pr_reviewer]
require_ticket_analysis_review=false
```
## Providers
### Github Issues Integration
Qodo Merge PR Agent will automatically recognize Github issues mentioned in the PR description and fetch the issue content.
Examples of valid GitHub issue references:
- `https://github.com/<ORG_NAME>/<REPO_NAME>/issues/<ISSUE_NUMBER>`
- `#<ISSUE_NUMBER>`
- `<ORG_NAME>/<REPO_NAME>#<ISSUE_NUMBER>`
Since Qodo Merge PR Agent is integrated with GitHub, it doesn't require any additional configuration to fetch GitHub issues.
### Jira Integration 💎
We support both Jira Cloud and Jira Server/Data Center.
To integrate with Jira, you can link your PR to a ticket using either of these methods:
**Method 1: Description Reference:**
Include a ticket reference in your PR description using either the complete URL format https://<JIRA_ORG>.atlassian.net/browse/ISSUE-123 or the shortened ticket ID ISSUE-123.
**Method 2: Branch Name Detection:**
Name your branch with the ticket ID as a prefix (e.g., `ISSUE-123-feature-description` or `ISSUE-123/feature-description`).
!!! note "Jira Base URL"
For shortened ticket IDs or branch detection (method 2), you must configure the Jira base URL in your configuration file under the [jira] section:
```toml
[jira]
jira_base_url = "https://<JIRA_ORG>.atlassian.net"
```
#### Jira Cloud 💎
There are two ways to authenticate with Jira Cloud:
**1) Jira App Authentication**
The recommended way to authenticate with Jira Cloud is to install the Qodo Merge app in your Jira Cloud instance. This will allow Qodo Merge to access Jira data on your behalf.
Installation steps:
1. Click [here](https://auth.atlassian.com/authorize?audience=api.atlassian.com&client_id=8krKmA4gMD8mM8z24aRCgPCSepZNP1xf&scope=read%3Ajira-work%20offline_access&redirect_uri=https%3A%2F%2Fregister.jira.pr-agent.codium.ai&state=qodomerge&response_type=code&prompt=consent) to install the Qodo Merge app in your Jira Cloud instance, click the `accept` button.<br>
![Jira Cloud App Installation](https://www.qodo.ai/images/pr_agent/jira_app_installation1.png){width=384}
2. After installing the app, you will be redirected to the Qodo Merge registration page. and you will see a success message.<br>
![Jira Cloud App success message](https://www.qodo.ai/images/pr_agent/jira_app_success.png){width=384}
3. Now you can use the Jira integration in Qodo Merge PR Agent.
**2) Email/Token Authentication**
You can create an API token from your Atlassian account:
1. Log in to https://id.atlassian.com/manage-profile/security/api-tokens.
2. Click Create API token.
3. From the dialog that appears, enter a name for your new token and click Create.
4. Click Copy to clipboard.
![Jira Cloud API Token](https://images.ctfassets.net/zsv3d0ugroxu/1RYvh9lqgeZjjNe5S3Hbfb/155e846a1cb38f30bf17512b6dfd2229/screenshot_NewAPIToken){width=384}
5. In your [configuration file](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/) add the following lines:
```toml
[jira]
jira_api_token = "YOUR_API_TOKEN"
jira_api_email = "YOUR_EMAIL"
```
#### Jira Data Center/Server 💎
##### Local App Authentication (For Qodo Merge On-Premise Customers)
##### 1. Step 1: Set up an application link in Jira Data Center/Server
* Go to Jira Administration > Applications > Application Links > Click on `Create link`
![application links](https://www.qodo.ai/images/pr_agent/jira_app_links.png){width=384}
* Choose `External application` and set the direction to `Incoming` and then click `Continue`
![external application](https://www.qodo.ai/images/pr_agent/jira_create_link.png){width=256}
* In the following screen, enter the following details:
* Name: `Qodo Merge`
* Redirect URL: Enter your Qodo Merge URL followed `https://{QODO_MERGE_ENDPOINT}/register_ticket_provider`
* Permission: Select `Read`
* Click `Save`
![external application details](https://www.qodo.ai/images/pr_agent/jira_fill_app_link.png){width=384}
* Copy the `Client ID` and `Client secret` and set them in your `.secrets` file:
![client id and secret](https://www.qodo.ai/images/pr_agent/jira_app_credentionals.png){width=256}
```toml
[jira]
jira_app_secret = "..."
jira_client_id = "..."
```
##### 2. Step 2: Authenticate with Jira Data Center/Server
* Open this URL in your browser: `https://{QODO_MERGE_ENDPOINT}/jira_auth`
* Click on link
![jira auth success](https://www.qodo.ai/images/pr_agent/jira_auth_page.png){width=384}
* You will be redirected to Jira Data Center/Server, click `Allow`
* You will be redirected back to Qodo Merge PR Agent and you will see a success message.
##### Personal Access Token (PAT) Authentication
We also support Personal Access Token (PAT) Authentication method.
1. Create a [Personal Access Token (PAT)](https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html) in your Jira account
2. In your Configuration file/Environment variables/Secrets file, add the following lines:
```toml
[jira]
jira_base_url = "YOUR_JIRA_BASE_URL" # e.g. https://jira.example.com
jira_api_token = "YOUR_API_TOKEN"
```

View File

@ -1,6 +1,8 @@
# Core Abilities # Core Abilities
Qodo Merge utilizes a variety of core abilities to provide a comprehensive and efficient code review experience. These abilities include: Qodo Merge utilizes a variety of core abilities to provide a comprehensive and efficient code review experience. These abilities include:
- [Fetching ticket context](https://qodo-merge-docs.qodo.ai/core-abilities/fetching_ticket_context/)
- [Auto best practices](https://qodo-merge-docs.qodo.ai/core-abilities/auto_best_practices/)
- [Local and global metadata](https://qodo-merge-docs.qodo.ai/core-abilities/metadata/) - [Local and global metadata](https://qodo-merge-docs.qodo.ai/core-abilities/metadata/)
- [Dynamic context](https://qodo-merge-docs.qodo.ai/core-abilities/dynamic_context/) - [Dynamic context](https://qodo-merge-docs.qodo.ai/core-abilities/dynamic_context/)
- [Self-reflection](https://qodo-merge-docs.qodo.ai/core-abilities/self_reflection/) - [Self-reflection](https://qodo-merge-docs.qodo.ai/core-abilities/self_reflection/)
@ -17,6 +19,7 @@ Here are some additional technical blogs from Qodo, that delve deeper into the c
These resources provide more comprehensive insights into leveraging LLMs for software development. These resources provide more comprehensive insights into leveraging LLMs for software development.
### Code Generation and LLMs ### Code Generation and LLMs
- [Effective AI code suggestions: less is more](https://www.qodo.ai/blog/effective-code-suggestions-llms-less-is-more/)
- [State-of-the-art Code Generation with AlphaCodium From Prompt Engineering to Flow Engineering](https://www.qodo.ai/blog/qodoflow-state-of-the-art-code-generation-for-code-contests/) - [State-of-the-art Code Generation with AlphaCodium From Prompt Engineering to Flow Engineering](https://www.qodo.ai/blog/qodoflow-state-of-the-art-code-generation-for-code-contests/)
- [RAG for a Codebase with 10k Repos](https://www.qodo.ai/blog/rag-for-large-scale-code-repos/) - [RAG for a Codebase with 10k Repos](https://www.qodo.ai/blog/rag-for-large-scale-code-repos/)

View File

@ -1,5 +1,5 @@
## Local and global metadata injection with multi-stage analysis ## Local and global metadata injection with multi-stage analysis
(1) 1\.
Qodo Merge initially retrieves for each PR the following data: Qodo Merge initially retrieves for each PR the following data:
- PR title and branch name - PR title and branch name
@ -11,7 +11,7 @@ Qodo Merge initially retrieves for each PR the following data:
!!! tip "Tip: Organization-level metadata" !!! tip "Tip: Organization-level metadata"
In addition to the inputs above, Qodo Merge can incorporate supplementary preferences provided by the user, like [`extra_instructions` and `organization best practices`](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices). This information can be used to enhance the PR analysis. In addition to the inputs above, Qodo Merge can incorporate supplementary preferences provided by the user, like [`extra_instructions` and `organization best practices`](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices). This information can be used to enhance the PR analysis.
(2) 2\.
By default, the first command that Qodo Merge executes is [`describe`](https://qodo-merge-docs.qodo.ai/tools/describe/), which generates three types of outputs: By default, the first command that Qodo Merge executes is [`describe`](https://qodo-merge-docs.qodo.ai/tools/describe/), which generates three types of outputs:
- PR Type (e.g. bug fix, feature, refactor, etc) - PR Type (e.g. bug fix, feature, refactor, etc)
@ -32,14 +32,14 @@ For example, when generating code suggestions for different files, Qodo Merge ca
@@ ... @@ def func1(): @@ ... @@ def func1():
__new hunk__ __new hunk__
11 unchanged code line0 in the PR 11 unchanged code line0
12 unchanged code line1 in the PR 12 unchanged code line1
13 +new code line2 added in the PR 13 +new code line2 added
14 unchanged code line3 in the PR 14 unchanged code line3
__old hunk__ __old hunk__
unchanged code line0 unchanged code line0
unchanged code line1 unchanged code line1
-old code line2 removed in the PR -old code line2 removed
unchanged code line3 unchanged code line3
@@ ... @@ def func2(): @@ ... @@ def func2():
@ -49,8 +49,8 @@ __old hunk__
... ...
``` ```
(3) The entire PR files that were retrieved are also used to expand and enhance the PR context (see [Dynamic Context](https://qodo-merge-docs.qodo.ai/core-abilities/dynamic_context/)). 3\. The entire PR files that were retrieved are also used to expand and enhance the PR context (see [Dynamic Context](https://qodo-merge-docs.qodo.ai/core-abilities/dynamic_context/)).
(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. 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. This comprehensive approach enables Qodo Merge AI models to generate more precise and contextually relevant suggestions and feedback.

View File

@ -46,6 +46,5 @@ This results in a more refined and valuable set of suggestions for the user, sav
## Appendix - Relevant Configuration Options ## Appendix - Relevant Configuration Options
``` ```
[pr_code_suggestions] [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) suggestions_score_threshold = 0 # Filter out suggestions with a score below this threshold (0-10)
``` ```

View File

@ -61,7 +61,7 @@ Or be triggered interactively by using the `analyze` tool.
### Find Similar Code ### Find Similar Code
The [`similar code`](https://qodo-merge-docs.qodo.ai/tools/similar_code/) tool retrieves the most similar code components from inside the organization's codebase, or from open-source code. The [`similar code`](https://qodo-merge-docs.qodo.ai/tools/similar_code/) tool retrieves the most similar code components from inside the organization's codebase or from open-source code, including details about the license associated with each repository.
For example: For example:

View File

@ -1,6 +1,6 @@
# FAQ # FAQ
??? note "Question: Can Qodo Merge serve as a substitute for a human reviewer?" ??? note "Q: Can Qodo Merge serve as a substitute for a human reviewer?"
#### Answer:<span style="display:none;">1</span> #### Answer:<span style="display:none;">1</span>
Qodo Merge is designed to assist, not replace, human reviewers. Qodo Merge is designed to assist, not replace, human reviewers.
@ -12,7 +12,7 @@
1. Preserves user's original PR header 1. Preserves user's original PR header
2. Places user's description above the AI-generated PR description 2. Places user's description above the AI-generated PR description
3. Cannot approve PRs; approval remains reviewer's responsibility 3. Won't approve PRs; approval remains reviewer's responsibility
4. The code suggestions are optional, and aim to: 4. The code suggestions are optional, and aim to:
- Encourage self-review and self-reflection - Encourage self-review and self-reflection
- Highlight potential bugs or oversights - Highlight potential bugs or oversights
@ -22,15 +22,15 @@
___ ___
??? note "Question: I received an incorrect or irrelevant suggestion. Why?" ??? note "Q: I received an incorrect or irrelevant suggestion. Why?"
#### Answer:<span style="display:none;">2</span> #### Answer:<span style="display:none;">2</span>
- Modern AI models, like Claude 3.5 Sonnet and GPT-4, are improving rapidly but remain imperfect. Users should critically evaluate all suggestions rather than accepting them automatically. - Modern AI models, like Claude 3.5 Sonnet and GPT-4, are improving rapidly but remain imperfect. Users should critically evaluate all suggestions rather than accepting them automatically.
- AI errors are rare, but possible. A main value from reviewing the code suggestions lies in their high probability of catching **mistakes or bugs made by the PR author**. We believe it's worth spending 30-60 seconds reviewing suggestions, even if some aren't relevant, as this practice can enhances code quality and prevent bugs in production. - AI errors are rare, but possible. A main value from reviewing the code suggestions lies in their high probability of catching **mistakes or bugs made by the PR author**. We believe it's worth spending 30-60 seconds reviewing suggestions, even if some aren't relevant, as this practice can enhance code quality and prevent bugs in production.
- 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: - The hierarchical structure of the suggestions is designed to help the user _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 `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. - 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.
@ -40,14 +40,14 @@ ___
___ ___
??? note "Question: How can I get more tailored suggestions?" ??? note "Q: How can I get more tailored suggestions?"
#### Answer:<span style="display:none;">3</span> #### Answer:<span style="display:none;">3</span>
See [here](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices) for more information on how to use the `extra_instructions` and `best_practices` configuration options, to guide the model to more tailored suggestions. See [here](https://qodo-merge-docs.qodo.ai/tools/improve/#extra-instructions-and-best-practices) for more information on how to use the `extra_instructions` and `best_practices` configuration options, to guide the model to more tailored suggestions.
___ ___
??? note "Question: Will you store my code ? Are you using my code to train models?" ??? note "Q: Will you store my code? Are you using my code to train models?"
#### Answer:<span style="display:none;">4</span> #### Answer:<span style="display:none;">4</span>
No. Qodo Merge strict privacy policy ensures that your code is not stored or used for training purposes. No. Qodo Merge strict privacy policy ensures that your code is not stored or used for training purposes.
@ -56,12 +56,35 @@ ___
___ ___
??? note "Question: Can I use my own LLM keys with Qodo Merge?" ??? note "Q: Can I use my own LLM keys with Qodo Merge?"
#### Answer:<span style="display:none;">5</span> #### Answer:<span style="display:none;">5</span>
When you self-host, you use your own keys. When you self-host the [open-source](https://github.com/Codium-ai/pr-agent) version, 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. Qodo Merge 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. For enterprise customers, on-prem deployment is also available. [Contact us](https://www.codium.ai/contact/#pricing) for more information.
___
??? note "Q: Can Qodo Merge review draft/offline PRs?"
#### Answer:<span style="display:none;">5</span>
Yes. While Qodo Merge won't automatically review draft PRs, you can still get feedback by manually requesting it through [online commenting](https://qodo-merge-docs.qodo.ai/usage-guide/automations_and_usage/#online-usage).
For active PRs, you can customize the automatic feedback settings [here](https://qodo-merge-docs.qodo.ai/usage-guide/automations_and_usage/#qodo-merge-automatic-feedback) to match your team's workflow.
___
??? note "Q: Can the 'Review effort' feedback be calibrated or customized?"
#### Answer:<span style="display:none;">5</span>
Yes, you can customize review effort estimates using the `extra_instructions` configuration option (see [documentation](https://qodo-merge-docs.qodo.ai/tools/review/#configuration-options)).
Example mapping:
- Effort 1: < 30 minutes review time
- Effort 2: 30-60 minutes review time
- Effort 3: 60-90 minutes review time
- ...
Note: The effort levels (1-5) are primarily meant for _comparative_ purposes, helping teams prioritize reviewing smaller PRs first. The actual review duration may vary, as the focus is on providing consistent relative effort estimates.
___ ___

View File

@ -1,15 +1,16 @@
# Overview # Overview
Qodo Merge is an open-source tool to help efficiently review and handle pull requests. [PR-Agent](https://github.com/Codium-ai/pr-agent) is an open-source tool to help efficiently review and handle pull requests.
Qodo Merge is a hosted version of PR-Agent, designed for companies and teams that require additional features and capabilities
- See the [Installation Guide](./installation/index.md) for instructions on installing and running the tool on different git platforms. - See the [Installation Guide](./installation/index.md) for instructions on installing and running the tool on different git platforms.
- See the [Usage Guide](./usage-guide/index.md) for instructions on running the Qodo Merge commands via different interfaces, including _CLI_, _online usage_, or by _automatically triggering_ them when a new PR is opened. - See the [Usage Guide](./usage-guide/index.md) for instructions on running commands via different interfaces, including _CLI_, _online usage_, or by _automatically triggering_ them when a new PR is opened.
- See the [Tools Guide](./tools/index.md) for a detailed description of the different tools. - See the [Tools Guide](./tools/index.md) for a detailed description of the different tools.
## Qodo Merge Docs Smart Search ## Docs Smart Search
To search the documentation site using natural language: To search the documentation site using natural language:
@ -18,12 +19,12 @@ To search the documentation site using natural language:
- A pull request where Qodo Merge is installed - A pull request where Qodo Merge is installed
- A [PR Chat](https://qodo-merge-docs.qodo.ai/chrome-extension/features/#pr-chat) - A [PR Chat](https://qodo-merge-docs.qodo.ai/chrome-extension/features/#pr-chat)
2) Qodo Merge will respond with an [answer](https://github.com/Codium-ai/pr-agent/pull/1241#issuecomment-2365259334) that includes relevant documentation links. 2) The bot will respond with an [answer](https://github.com/Codium-ai/pr-agent/pull/1241#issuecomment-2365259334) that includes relevant documentation links.
## Qodo Merge Features ## Qodo Merge Features
Qodo Merge offers extensive pull request functionalities across various git providers. Qodo Merge offers extensive pull request functionalities across various git providers:
| | | GitHub | Gitlab | Bitbucket | Azure DevOps | | | | GitHub | Gitlab | Bitbucket | Azure DevOps |
|-------|-----------------------------------------------------------------------------------------------------------------------|:------:|:------:|:---------:|:------------:| |-------|-----------------------------------------------------------------------------------------------------------------------|:------:|:------:|:---------:|:------------:|
@ -31,16 +32,19 @@ Qodo Merge offers extensive pull request functionalities across various git prov
| | ⮑ Incremental | ✅ | | | | | | ⮑ Incremental | ✅ | | | |
| | Ask | ✅ | ✅ | ✅ | ✅ | | | Ask | ✅ | ✅ | ✅ | ✅ |
| | Describe | ✅ | ✅ | ✅ | ✅ | | | Describe | ✅ | ✅ | ✅ | ✅ |
| | ⮑ [Inline file summary](https://qodo-merge-docs.qodo.ai/tools/describe/#inline-file-summary){:target="_blank"} 💎 | ✅ | ✅ | | | | | ⮑ [Inline file summary](https://qodo-merge-docs.qodo.ai/tools/describe/#inline-file-summary){:target="_blank"} 💎 | ✅ | ✅ | | |
| | Improve | ✅ | ✅ | ✅ | ✅ | | | Improve | ✅ | ✅ | ✅ | ✅ |
| | ⮑ Extended | ✅ | ✅ | ✅ | ✅ | | | ⮑ Extended | ✅ | ✅ | ✅ | ✅ |
| | [Custom Prompt](./tools/custom_prompt.md){:target="_blank"} 💎 | ✅ | ✅ | ✅ | | | | [Auto-Approve](https://qodo-merge-docs.qodo.ai/tools/improve/#auto-approval) 💎 | ✅ | ✅ | ✅ | |
| | Reflect and Review | ✅ | ✅ | | | | | [Custom Prompt](./tools/custom_prompt.md){:target="_blank"} 💎 | ✅ | ✅ | | |
| | Reflect and Review | ✅ | ✅ | ✅ | ✅ |
| | Update CHANGELOG.md | ✅ | ✅ | ✅ | | | | Update CHANGELOG.md | ✅ | ✅ | ✅ | |
| | Find Similar Issue | ✅ | | | | | | Find Similar Issue | ✅ | | | |
| | [Add PR Documentation](./tools/documentation.md){:target="_blank"} 💎 | ✅ | ✅ | | | | | [Add PR Documentation](./tools/documentation.md){:target="_blank"} 💎 | ✅ | ✅ | | |
| | [Generate Custom Labels](./tools/describe.md#handle-custom-labels-from-the-repos-labels-page-💎){:target="_blank"} 💎 | ✅ | ✅ | | | | | [Generate Custom Labels](./tools/describe.md#handle-custom-labels-from-the-repos-labels-page-💎){:target="_blank"} 💎 | ✅ | ✅ | | |
| | [Analyze PR Components](./tools/analyze.md){:target="_blank"} 💎 | ✅ | ✅ | | | | | [Analyze PR Components](./tools/analyze.md){:target="_blank"} 💎 | ✅ | ✅ | | |
| | [Test](https://pr-agent-docs.codium.ai/tools/test/) 💎 | ✅ | ✅ | | |
| | [Implement](https://pr-agent-docs.codium.ai/tools/implement/) 💎 | ✅ | ✅ | ✅ | |
| | | | | | | | | | | | | |
| USAGE | CLI | ✅ | ✅ | ✅ | ✅ | | USAGE | CLI | ✅ | ✅ | ✅ | ✅ |
| | App / webhook | ✅ | ✅ | ✅ | ✅ | | | App / webhook | ✅ | ✅ | ✅ | ✅ |
@ -50,11 +54,10 @@ Qodo Merge offers extensive pull request functionalities across various git prov
| | Repo language prioritization | ✅ | ✅ | ✅ | ✅ | | | Repo language prioritization | ✅ | ✅ | ✅ | ✅ |
| | Adaptive and token-aware file patch fitting | ✅ | ✅ | ✅ | ✅ | | | Adaptive and token-aware file patch fitting | ✅ | ✅ | ✅ | ✅ |
| | Multiple models support | ✅ | ✅ | ✅ | ✅ | | | Multiple models support | ✅ | ✅ | ✅ | ✅ |
| | Incremental PR review | ✅ | | | | | | [Static code analysis](./core-abilities/static_code_analysis/){:target="_blank"} 💎 | ✅ | ✅ | | |
| | [Static code analysis](./tools/analyze.md/){:target="_blank"} 💎 | ✅ | ✅ | ✅ | | | | [Multiple configuration options](./usage-guide/configuration_options.md){:target="_blank"} 💎 | ✅ | ✅ | | |
| | [Multiple configuration options](./usage-guide/configuration_options.md){:target="_blank"} 💎 | ✅ | ✅ | ✅ | |
💎 marks a feature available only in [Qodo Merge Pro](https://www.codium.ai/pricing/){:target="_blank"} 💎 marks a feature available only in [Qodo Merge](https://www.codium.ai/pricing/){:target="_blank"}, and not in the open-source version.
## Example Results ## Example Results
@ -90,4 +93,4 @@ The following diagram illustrates Qodo Merge tools and their flow:
![Qodo Merge Tools](https://codium.ai/images/pr_agent/diagram-v0.9.png) ![Qodo Merge Tools](https://codium.ai/images/pr_agent/diagram-v0.9.png)
Check out the [core abilities](core-abilities/index.md) page for a comprehensive overview of the variety of core abilities used by Qodo Merge. 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

View File

@ -1,5 +1,5 @@
## Azure DevOps Pipeline ## Azure DevOps Pipeline
You can use a pre-built Action Docker image to run Qodo Merge as an Azure devops pipeline. You can use a pre-built Action Docker image to run PR-Agent as an Azure devops pipeline.
add the following file to your repository under `azure-pipelines.yml`: add the following file to your repository under `azure-pipelines.yml`:
```yaml ```yaml
# Opt out of CI triggers # Opt out of CI triggers
@ -51,10 +51,12 @@ stages:
``` ```
This script will run Qodo Merge on every new merge request, with the `improve`, `review`, and `describe` commands. This script will run Qodo Merge on every new merge request, with the `improve`, `review`, and `describe` commands.
Note that you need to export the `azure_devops__pat` and `OPENAI_KEY` variables in the Azure DevOps pipeline settings (Pipelines -> Library -> + Variable group): Note that you need to export the `azure_devops__pat` and `OPENAI_KEY` variables in the Azure DevOps pipeline settings (Pipelines -> Library -> + Variable group):
![Qodo Merge Pro](https://codium.ai/images/pr_agent/azure_devops_pipeline_secrets.png){width=468}
![Qodo Merge](https://codium.ai/images/pr_agent/azure_devops_pipeline_secrets.png){width=468}
Make sure to give pipeline permissions to the `pr_agent` variable group. Make sure to give pipeline permissions to the `pr_agent` variable group.
> Note that Azure Pipelines lacks support for triggering workflows from PR comments. If you find a viable solution, please contribute it to our [issue tracker](https://github.com/Codium-ai/pr-agent/issues)
## Azure DevOps from CLI ## Azure DevOps from CLI
@ -78,7 +80,7 @@ org = "https://dev.azure.com/YOUR_ORGANIZATION/"
# pat = "YOUR_PAT_TOKEN" needed only if using PAT for authentication # pat = "YOUR_PAT_TOKEN" needed only if using PAT for authentication
``` ```
### Azure DevOps Webhook ## 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 /<command> <args> comment on the relevant PR. Note that for the "Pull request commented on" trigger, only API v2.0 is supported. Use the "Pull request created" type to trigger a review, or "Pull request commented on" to trigger any supported comment with /<command> <args> comment on the relevant PR. Note that for the "Pull request commented on" trigger, only API v2.0 is supported.

View File

@ -27,10 +27,6 @@ You can get a Bitbucket token for your repository by following Repository Settin
Note that comments on a PR are not supported in Bitbucket Pipeline. Note that comments on a PR are not supported in Bitbucket Pipeline.
## Run using CodiumAI-hosted Bitbucket app 💎
Please contact visit [Qodo Merge Pro](https://www.codium.ai/pricing/) if you're interested in a hosted BitBucket app solution that provides full functionality including PR reviews and comment handling. It's based on the [bitbucket_app.py](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/git_providers/bitbucket_provider.py) implementation.
## Bitbucket Server and Data Center ## Bitbucket Server and Data Center

View File

@ -1,6 +1,6 @@
## Run as a GitHub Action ## Run as a GitHub Action
You can use our pre-built Github Action Docker image to run Qodo Merge as a Github Action. You can use our pre-built Github Action Docker image to run PR-Agent as a Github Action.
1) Add the following file to your repository under `.github/workflows/pr_agent.yml`: 1) Add the following file to your repository under `.github/workflows/pr_agent.yml`:
@ -21,7 +21,7 @@ jobs:
steps: steps:
- name: PR Agent action step - name: PR Agent action step
id: pragent id: pragent
uses: Codium-ai/pr-agent@main uses: qodo-ai/pr-agent@main
env: env:
OPENAI_KEY: ${{ secrets.OPENAI_KEY }} OPENAI_KEY: ${{ secrets.OPENAI_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,5 +1,5 @@
## Run as a GitLab Pipeline ## Run as a GitLab Pipeline
You can use a pre-built Action Docker image to run Qodo Merge as a GitLab pipeline. This is a simple way to get started with Qodo Merge without setting up your own server. You can use a pre-built Action Docker image to run PR-Agent as a GitLab pipeline. This is a simple way to get started with Qodo Merge without setting up your own server.
(1) Add the following file to your repository under `.gitlab-ci.yml`: (1) Add the following file to your repository under `.gitlab-ci.yml`:
```yaml ```yaml
@ -38,6 +38,7 @@ You can also modify the `script` section to run different Qodo Merge commands, o
Note that if your base branches are not protected, don't set the variables as `protected`, since the pipeline will not have access to them. Note that if your base branches are not protected, don't set the variables as `protected`, since the pipeline will not have access to them.
> **Note**: The `$CI_SERVER_FQDN` variable is available starting from GitLab version 16.10. If you're using an earlier version, this variable will not be available. However, you can combine `$CI_SERVER_HOST` and `$CI_SERVER_PORT` to achieve the same result. Please ensure you're using a compatible version or adjust your configuration.
## Run a GitLab webhook server ## Run a GitLab webhook server

View File

@ -1,21 +1,17 @@
# Installation # Installation
## Self-hosted Qodo Merge ## Self-hosted PR-Agent
If you choose to host your own Qodo Merge, you first need to acquire two tokens:
1. An OpenAI key from [here](https://platform.openai.com/api-keys), with access to GPT-4 (or a key for other [language models](https://qodo-merge-docs.qodo.ai/usage-guide/changing_a_model/), if you prefer). There are several ways to use self-hosted PR-Agent:
2. A GitHub\GitLab\BitBucket personal access token (classic), with the repo scope. [GitHub from [here](https://github.com/settings/tokens)]
There are several ways to use self-hosted Qodo Merge:
- [Locally](./locally.md) - [Locally](./locally.md)
- [GitHub](./github.md) - [GitHub integration](./github.md)
- [GitLab](./gitlab.md) - [GitLab integration](./gitlab.md)
- [BitBucket](./bitbucket.md) - [BitBucket integration](./bitbucket.md)
- [Azure DevOps](./azure.md) - [Azure DevOps integration](./azure.md)
## Qodo Merge Pro 💎 ## Qodo Merge 💎
Qodo Merge Pro, an app hosted by CodiumAI for GitHub\GitLab\BitBucket, is also available. Qodo Merge, an app hosted by QodoAI for GitHub\GitLab\BitBucket, is also available.
<br> <br>
With Qodo Merge Pro, installation is as simple as signing up and adding the Qodo Merge app to your relevant repo. With Qodo Merge, installation is as simple as adding the Qodo Merge app to your relevant repositories.
See [here](https://qodo-merge-docs.qodo.ai/installation/pr_agent_pro/) for more details. See [here](https://qodo-merge-docs.qodo.ai/installation/qodo_merge/) for more details.

View File

@ -1,3 +1,77 @@
To run PR-Agent locally, you first need to acquire two keys:
1. An OpenAI key from [here](https://platform.openai.com/api-keys){:target="_blank"}, with access to GPT-4 (or a key for other [language models](https://qodo-merge-docs.qodo.ai/usage-guide/changing_a_model/), if you prefer).
2. A personal access token from your Git platform (GitHub, GitLab, BitBucket) with repo scope. GitHub token, for example, can be issued from [here](https://github.com/settings/tokens){:target="_blank"}
## Using Docker image
A list of the relevant tools can be found in the [tools guide](../tools/ask.md).
To invoke a tool (for example `review`), you can run PR-Agent directly from the Docker image. Here's how:
- For GitHub:
```
docker run --rm -it -e OPENAI.KEY=<your key> -e GITHUB.USER_TOKEN=<your token> codiumai/pr-agent:latest --pr_url <pr_url> review
```
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
```
- For GitLab:
```
docker run --rm -it -e OPENAI.KEY=<your key> -e CONFIG.GIT_PROVIDER=gitlab -e GITLAB.PERSONAL_ACCESS_TOKEN=<your token> codiumai/pr-agent:latest --pr_url <pr_url> review
```
If you have a dedicated GitLab instance, you need to specify the custom url as variable:
```
-e GITLAB.URL=<your gitlab instance url>
```
- For BitBucket:
```
docker run --rm -it -e CONFIG.GIT_PROVIDER=bitbucket -e OPENAI.KEY=$OPENAI_API_KEY -e BITBUCKET.BEARER_TOKEN=$BITBUCKET_BEARER_TOKEN codiumai/pr-agent:latest --pr_url=<pr_url> review
```
For other git providers, update `CONFIG.GIT_PROVIDER` accordingly and check the [`pr_agent/settings/.secrets_template.toml`](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/.secrets_template.toml) file for environment variables expected names and values.
### Utilizing environment variables
It is also possible to provide or override the configuration by setting the corresponding environment variables.
You can define the corresponding environment variables by following this convention: `<TABLE>__<KEY>=<VALUE>` or `<TABLE>.<KEY>=<VALUE>`.
The `<TABLE>` refers to a table/section in a configuration file and `<KEY>=<VALUE>` refers to the key/value pair of a setting in the configuration file.
For example, suppose you want to run `pr_agent` that connects to a self-hosted GitLab instance similar to an example above.
You can define the environment variables in a plain text file named `.env` with the following content:
```
CONFIG__GIT_PROVIDER="gitlab"
GITLAB__URL="<your url>"
GITLAB__PERSONAL_ACCESS_TOKEN="<your token>"
OPENAI__KEY="<your key>"
```
Then, you can run `pr_agent` using Docker with the following command:
```shell
docker run --rm -it --env-file .env codiumai/pr-agent:latest <tool> <tool parameter>
```
---
### I get an error when running the Docker image. What should I do?
If you encounter an error when running the Docker image, it is almost always due to a misconfiguration of api keys or tokens.
Note that litellm, which is used by pr-agent, sometimes returns non-informative error messages such as `APIError: OpenAIException - Connection error.`
Carefully check the api keys and tokens you provided and make sure they are correct.
Adjustments may be needed depending on your llm provider.
For example, for Azure OpenAI, additional keys are [needed](https://qodo-merge-docs.qodo.ai/usage-guide/changing_a_model/#azure).
Same goes for other providers, make sure to check the [documentation](https://qodo-merge-docs.qodo.ai/usage-guide/changing_a_model/#changing-a-model)
## Using pip package ## Using pip package
Install the package: Install the package:
@ -35,40 +109,6 @@ if __name__ == '__main__':
main() main()
``` ```
## Using Docker image
A list of the relevant tools can be found in the [tools guide](../tools/ask.md).
To invoke a tool (for example `review`), you can run directly from the Docker image. Here's how:
- For GitHub:
```
docker run --rm -it -e OPENAI.KEY=<your key> -e GITHUB.USER_TOKEN=<your token> codiumai/pr-agent:latest --pr_url <pr_url> review
```
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
```
- For GitLab:
```
docker run --rm -it -e OPENAI.KEY=<your key> -e CONFIG.GIT_PROVIDER=gitlab -e GITLAB.PERSONAL_ACCESS_TOKEN=<your token> codiumai/pr-agent:latest --pr_url <pr_url> review
```
If you have a dedicated GitLab instance, you need to specify the custom url as variable:
```
-e GITLAB.URL=<your gitlab instance url>
```
- For BitBucket:
```
docker run --rm -it -e CONFIG.GIT_PROVIDER=bitbucket -e OPENAI.KEY=$OPENAI_API_KEY -e BITBUCKET.BEARER_TOKEN=$BITBUCKET_BEARER_TOKEN codiumai/pr-agent:latest --pr_url=<pr_url> review
```
For other git providers, update CONFIG.GIT_PROVIDER accordingly, and check the `pr_agent/settings/.secrets_template.toml` file for the environment variables expected names and values.
---
## Run from source ## Run from source

View File

@ -0,0 +1,49 @@
# PR-Agent Installation Guide
PR-Agent can be deployed in various environments and platforms. Choose the installation method that best suits your needs:
## 🖥️ Local Installation
Learn how to run PR-Agent locally using:
- Docker image
- pip package
- CLI from source code
[View Local Installation Guide →](https://qodo-merge-docs.qodo.ai/installation/locally/)
## 🐙 GitHub Integration
Set up PR-Agent with GitHub as:
- GitHub Action
- Local GitHub App
[View GitHub Integration Guide →](https://qodo-merge-docs.qodo.ai/installation/github/)
## 🦊 GitLab Integration
Deploy PR-Agent on GitLab as:
- GitLab pipeline job
- Local GitLab webhook server
[View GitLab Integration Guide →](https://qodo-merge-docs.qodo.ai/installation/gitlab/)
## 🟦 BitBucket Integration
Implement PR-Agent in BitBucket as:
- BitBucket pipeline job
- Local BitBucket server
[View BitBucket Integration Guide →](https://qodo-merge-docs.qodo.ai/installation/bitbucket/)
## 🔷 Azure DevOps Integration
Configure PR-Agent with Azure DevOps as:
- Azure DevOps pipeline job
- Local Azure DevOps webhook
[View Azure DevOps Integration Guide →](https://qodo-merge-docs.qodo.ai/installation/azure/)

View File

@ -1,68 +0,0 @@
## Getting Started with Qodo Merge Pro
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/).
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.
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.
Users without a purchased seat who interact with a repository featuring Qodo Merge Pro are entitled to receive up to five complimentary feedbacks.
Beyond this limit, Qodo Merge Pro will cease to respond to their inquiries unless a seat is purchased.
## Install Qodo Merge Pro for GitHub Enterprise Server
To use Qodo Merge Pro application on your private GitHub Enterprise Server, you will need to contact us for starting an [Enterprise](https://www.codium.ai/pricing/) trial.
## Install Qodo Merge Pro for GitLab (Teams & Enterprise)
Since GitLab platform does not support apps, installing Qodo Merge Pro for GitLab is a bit more involved, and requires the following steps:
### Step 1
Acquire a personal, project or group level access token. Enable the “api” scope in order to allow Qodo Merge to read pull requests, comment and respond to requests.
<figure markdown="1">
![Step 1](https://www.codium.ai/images/pr_agent/gitlab_pro_pat.png){width=750}
</figure>
Store the token in a safe place, you wont be able to access it again after it was generated.
### Step 2
Generate a shared secret and link it to the access token. Browse to [https://register.gitlab.pr-agent.codium.ai](https://register.gitlab.pr-agent.codium.ai).
Fill in your generated GitLab token and your company or personal name in the appropriate fields and click "Submit".
You should see "Success!" displayed above the Submit button, and a shared secret will be generated. Store it in a safe place, you wont be able to access it again after it was generated.
### Step 3
Install a webhook for your repository or groups, by clicking “webhooks” on the settings menu. Click the “Add new webhook” button.
<figure markdown="1">
![Step 3.1](https://www.codium.ai/images/pr_agent/gitlab_pro_add_webhook.png)
</figure>
In the webhook definition form, fill in the following fields:
URL: https://pro.gitlab.pr-agent.codium.ai/webhook
Secret token: Your CodiumAI key
Trigger: Check the comments and merge request events boxes.
Enable SSL verification: Check the box.
<figure markdown="1">
![Step 3.2](https://www.codium.ai/images/pr_agent/gitlab_pro_webhooks.png){width=750}
</figure>
### Step 4
Youre all set!
Open a new merge request or add a MR comment with one of Qodo Merges commands such as /review, /describe or /improve.

View File

@ -0,0 +1,87 @@
Qodo Merge is a versatile application compatible with GitHub, GitLab, and BitBucket, hosted by QodoAI.
See [here](https://qodo-merge-docs.qodo.ai/overview/pr_agent_pro/) for more details about the benefits of using Qodo Merge.
A complimentary two-week trial is provided to all new users. Following the trial period, user licenses (seats) are required for continued access.
To purchase user licenses, please visit our [pricing page](https://www.qodo.ai/pricing/).
Once subscribed, users can seamlessly deploy the application across any of their code repositories.
## Install Qodo Merge for GitHub
### GitHub Cloud
Qodo Merge for GitHub cloud is available for installation through the [GitHub Marketplace](https://github.com/apps/qodo-merge-pro).
![Qodo Merge](https://codium.ai/images/pr_agent/pr_agent_pro_install.png){width=468}
### GitHub Enterprise Server
To use Qodo Merge application on your private GitHub Enterprise Server, you will need to [contact](https://www.qodo.ai/contact/#pricing) Qodo for starting an Enterprise trial.
### GitHub Open Source Projects
For open-source projects, Qodo Merge is available for free usage. To install Qodo Merge for your open-source repositories, use the following marketplace [link](https://github.com/apps/qodo-merge-pro-for-open-source).
## Install Qodo Merge for Bitbucket
### Bitbucket Cloud
Qodo Merge for Bitbucket Cloud is available for installation through the following [link](https://bitbucket.org/site/addons/authorize?addon_key=d6df813252c37258)
![Qodo Merge](https://qodo.ai/images/pr_agent/pr_agent_pro_bitbucket_install.png){width=468}
### Bitbucket Server
To use Qodo Merge application on your private Bitbucket Server, you will need to contact us for starting an [Enterprise](https://www.qodo.ai/pricing/) trial.
## Install Qodo Merge for GitLab
### GitLab Cloud
Since GitLab platform does not support apps, installing Qodo Merge for GitLab is a bit more involved, and requires the following steps:
#### Step 1
Acquire a personal, project or group level access token. Enable the “api” scope in order to allow Qodo Merge to read pull requests, comment and respond to requests.
<figure markdown="1">
![Step 1](https://www.codium.ai/images/pr_agent/gitlab_pro_pat.png){width=750}
</figure>
Store the token in a safe place, you wont be able to access it again after it was generated.
#### Step 2
Generate a shared secret and link it to the access token. Browse to [https://register.gitlab.pr-agent.codium.ai](https://register.gitlab.pr-agent.codium.ai).
Fill in your generated GitLab token and your company or personal name in the appropriate fields and click "Submit".
You should see "Success!" displayed above the Submit button, and a shared secret will be generated. Store it in a safe place, you wont be able to access it again after it was generated.
#### Step 3
Install a webhook for your repository or groups, by clicking “webhooks” on the settings menu. Click the “Add new webhook” button.
<figure markdown="1">
![Step 3.1](https://www.codium.ai/images/pr_agent/gitlab_pro_add_webhook.png)
</figure>
In the webhook definition form, fill in the following fields:
URL: https://pro.gitlab.pr-agent.codium.ai/webhook
Secret token: Your QodoAI key
Trigger: Check the comments and merge request events boxes.
Enable SSL verification: Check the box.
<figure markdown="1">
![Step 3.2](https://www.codium.ai/images/pr_agent/gitlab_pro_webhooks.png){width=750}
</figure>
#### Step 4
Youre all set!
Open a new merge request or add a MR comment with one of Qodo Merges commands such as /review, /describe or /improve.
### GitLab Server
For a trial period of two weeks on your private GitLab Server, the same [installation steps](#gitlab-cloud) as for GitLab Cloud apply. After the trial period, you will need to [contact](https://www.qodo.ai/contact/#pricing) Qodo for moving to an Enterprise account.

View File

@ -1,12 +1,12 @@
## Self-hosted Qodo Merge ## Self-hosted PR-Agent
- If you self-host Qodo Merge with your OpenAI (or other LLM provider) API key, it is between you and the provider. We don't send your code data to Qodo Merge servers. - If you self-host PR-Agent with your OpenAI (or other LLM provider) API key, it is between you and the provider. We don't send your code data to Qodo servers.
## Qodo Merge Pro 💎 ## Qodo Merge 💎
- When using Qodo Merge Pro 💎, hosted by CodiumAI, we will not store any of your data, nor will we use it for training. You will also benefit from an OpenAI account with zero data retention. - When using Qodo Merge💎, hosted by Qodo, we will not store any of your data, nor will we use it for training. You will also benefit from an OpenAI account with zero data retention.
- For certain clients, CodiumAI-hosted Qodo Merge Pro will use CodiumAIs proprietary models. If this is the case, you will be notified. - For certain clients, Qodo Merge will use Qodos proprietary models. If this is the case, you will be notified.
- No passive collection of Code and Pull Requests data — Qodo Merge will be active only when you invoke it, and it will then extract and analyze only data relevant to the executed command and queried pull request. - No passive collection of Code and Pull Requests data — Qodo Merge will be active only when you invoke it, and it will then extract and analyze only data relevant to the executed command and queried pull request.

View File

@ -1,93 +0,0 @@
# Overview
Qodo Merge is an open-source tool to help efficiently review and handle pull requests.
- See the [Installation Guide](./installation/index.md) for instructions on installing and running the tool on different git platforms.
- See the [Usage Guide](./usage-guide/index.md) for instructions on running the Qodo Merge commands via different interfaces, including _CLI_, _online usage_, or by _automatically triggering_ them when a new PR is opened.
- See the [Tools Guide](./tools/index.md) for a detailed description of the different tools.
## Qodo Merge Docs Smart Search
To search the documentation site using natural language:
1) Comment `/help "your question"` in either:
- A pull request where Qodo Merge is installed
- A [PR Chat](https://qodo-merge-docs.qodo.ai/chrome-extension/features/#pr-chat)
2) Qodo Merge will respond with an [answer](https://github.com/Codium-ai/pr-agent/pull/1241#issuecomment-2365259334) that includes relevant documentation links.
## Qodo Merge Features
Qodo Merge offers extensive pull request functionalities across various git providers.
| | | GitHub | Gitlab | Bitbucket | Azure DevOps |
|-------|-----------------------------------------------------------------------------------------------------------------------|:------:|:------:|:---------:|:------------:|
| TOOLS | Review | ✅ | ✅ | ✅ | ✅ |
| | ⮑ Incremental | ✅ | | | |
| | Ask | ✅ | ✅ | ✅ | ✅ |
| | Describe | ✅ | ✅ | ✅ | ✅ |
| | ⮑ [Inline file summary](https://qodo-merge-docs.qodo.ai/tools/describe/#inline-file-summary){:target="_blank"} 💎 | ✅ | ✅ | | ✅ |
| | Improve | ✅ | ✅ | ✅ | ✅ |
| | ⮑ Extended | ✅ | ✅ | ✅ | ✅ |
| | [Custom Prompt](./tools/custom_prompt.md){:target="_blank"} 💎 | ✅ | ✅ | ✅ | ✅ |
| | Reflect and Review | ✅ | ✅ | ✅ | ✅ |
| | Update CHANGELOG.md | ✅ | ✅ | ✅ | |
| | Find Similar Issue | ✅ | | | |
| | [Add PR Documentation](./tools/documentation.md){:target="_blank"} 💎 | ✅ | ✅ | | ✅ |
| | [Generate Custom Labels](./tools/describe.md#handle-custom-labels-from-the-repos-labels-page-💎){:target="_blank"} 💎 | ✅ | ✅ | | ✅ |
| | [Analyze PR Components](./tools/analyze.md){:target="_blank"} 💎 | ✅ | ✅ | | ✅ |
| | | | | | |
| USAGE | CLI | ✅ | ✅ | ✅ | ✅ |
| | App / webhook | ✅ | ✅ | ✅ | ✅ |
| | Actions | ✅ | | | |
| | | | | |
| CORE | PR compression | ✅ | ✅ | ✅ | ✅ |
| | Repo language prioritization | ✅ | ✅ | ✅ | ✅ |
| | Adaptive and token-aware file patch fitting | ✅ | ✅ | ✅ | ✅ |
| | Multiple models support | ✅ | ✅ | ✅ | ✅ |
| | Incremental PR review | ✅ | | | |
| | [Static code analysis](./tools/analyze.md/){:target="_blank"} 💎 | ✅ | ✅ | ✅ | ✅ |
| | [Multiple configuration options](./usage-guide/configuration_options.md){:target="_blank"} 💎 | ✅ | ✅ | ✅ | ✅ |
💎 marks a feature available only in [Qodo Merge Pro](https://www.codium.ai/pricing/){:target="_blank"}
## Example Results
<hr>
#### [/describe](https://github.com/Codium-ai/pr-agent/pull/530)
<figure markdown="1">
![/describe](https://www.codium.ai/images/pr_agent/describe_new_short_main.png){width=512}
</figure>
<hr>
#### [/review](https://github.com/Codium-ai/pr-agent/pull/732#issuecomment-1975099151)
<figure markdown="1">
![/review](https://www.codium.ai/images/pr_agent/review_new_short_main.png){width=512}
</figure>
<hr>
#### [/improve](https://github.com/Codium-ai/pr-agent/pull/732#issuecomment-1975099159)
<figure markdown="1">
![/improve](https://www.codium.ai/images/pr_agent/improve_new_short_main.png){width=512}
</figure>
<hr>
#### [/generate_labels](https://github.com/Codium-ai/pr-agent/pull/530)
<figure markdown="1">
![/generate_labels](https://www.codium.ai/images/pr_agent/geneare_custom_labels_main_short.png){width=300}
</figure>
<hr>
## How it Works
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

View File

@ -1,21 +1,21 @@
### Overview ### Overview
[Qodo Merge Pro](https://www.codium.ai/pricing/) is a hosted version of Qodo Merge, provided by Qodo. A complimentary two-week trial is offered, followed by a monthly subscription fee. [Qodo Merge](https://www.codium.ai/pricing/){:target="_blank"} is a paid, hosted version of open-source [PR-Agent](https://github.com/Codium-ai/pr-agent){:target="_blank"}. A complimentary two-week trial is offered, followed by a monthly subscription fee.
Qodo Merge Pro is designed for companies and teams that require additional features and capabilities. It provides the following benefits: Qodo Merge is designed for companies and teams that require additional features and capabilities. It provides the following benefits:
1. **Fully managed** - We take care of everything for you - hosting, models, regular updates, and more. Installation is as simple as signing up and adding the Qodo Merge app to your GitHub\GitLab\BitBucket repo. 1. **Fully managed** - We take care of everything for you - hosting, models, regular updates, and more. Installation is as simple as signing up and adding the Qodo Merge app to your GitHub\GitLab\BitBucket repo.
2. **Improved privacy** - No data will be stored or used to train models. Qodo Merge Pro will employ zero data retention, and will use an OpenAI and Claude accounts with zero data retention. 2. **Improved privacy** - No data will be stored or used to train models. Qodo Merge will employ zero data retention, and will use an OpenAI and Claude accounts with zero data retention.
3. **Improved support** - Qodo Merge Pro users will receive priority support, and will be able to request new features and capabilities. 3. **Improved support** - Qodo Merge users will receive priority support, and will be able to request new features and capabilities.
4. **Supporting self-hosted git servers** - Qodo Merge Pro can be installed on GitHub Enterprise Server, GitLab, and BitBucket. For more information, see the [installation guide](https://qodo-merge-docs.qodo.ai/installation/pr_agent_pro/). 4. **Supporting self-hosted git servers** - Qodo Merge can be installed on GitHub Enterprise Server, GitLab, and BitBucket. For more information, see the [installation guide](https://qodo-merge-docs.qodo.ai/installation/pr_agent_pro/).
5. **PR Chat** - Qodo Merge Pro allows you to engage in [private chat](https://qodo-merge-docs.qodo.ai/chrome-extension/features/#pr-chat) about your pull requests on private repositories. 5. **PR Chat** - Qodo Merge allows you to engage in [private chat](https://qodo-merge-docs.qodo.ai/chrome-extension/features/#pr-chat) about your pull requests on private repositories.
### Additional features ### Additional features
Here are some of the additional features and capabilities that Qodo Merge Pro offers: Here are some of the additional features and capabilities that Qodo Merge offers:
| Feature | Description | | Feature | Description |
|----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------| |----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@ -24,28 +24,29 @@ Here are some of the additional features and capabilities that Qodo Merge Pro of
| [**Apply suggestions**](https://qodo-merge-docs.qodo.ai/tools/improve/#overview) | Generate committable code from the relevant suggestions interactively by clicking on a checkbox | | [**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 | | [**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 |
| [**CI feedback**](https://qodo-merge-docs.qodo.ai/tools/ci_feedback/) | Automatically analyze failed CI checks on GitHub and provide actionable feedback in the PR conversation, helping to resolve issues quickly | | [**CI feedback**](https://qodo-merge-docs.qodo.ai/tools/ci_feedback/) | Automatically analyze failed CI checks on GitHub and provide actionable feedback in the PR conversation, helping to resolve issues quickly |
| [**Advanced usage statistics**](https://www.codium.ai/contact/#/) | Qodo Merge Pro offers detailed statistics at user, repository, and company levels, including metrics about Qodo Merge usage, and also general statistics and insights | | [**Advanced usage statistics**](https://www.codium.ai/contact/#/) | Qodo Merge offers detailed statistics at user, repository, and company levels, including metrics about Qodo Merge usage, and also general statistics and insights |
| [**Incorporating companies' best practices**](https://qodo-merge-docs.qodo.ai/tools/improve/#best-practices) | Use the companies' best practices as reference to increase the effectiveness and the relevance of the code suggestions | | [**Incorporating companies' best practices**](https://qodo-merge-docs.qodo.ai/tools/improve/#best-practices) | Use the companies' best practices as reference to increase the effectiveness and the relevance of the code suggestions |
| [**Interactive triggering**](https://qodo-merge-docs.qodo.ai/tools/analyze/#example-usage) | Interactively apply different tools via the `analyze` command | | [**Interactive triggering**](https://qodo-merge-docs.qodo.ai/tools/analyze/#example-usage) | Interactively apply different tools via the `analyze` command |
| [**Custom labels**](https://qodo-merge-docs.qodo.ai/tools/describe/#handle-custom-labels-from-the-repos-labels-page) | Define custom labels for Qodo Merge to assign to the PR | | [**Custom labels**](https://qodo-merge-docs.qodo.ai/tools/describe/#handle-custom-labels-from-the-repos-labels-page) | Define custom labels for Qodo Merge to assign to the PR |
### Additional tools ### Additional tools
Here are additional tools that are available only for Qodo Merge Pro users: Here are additional tools that are available only for Qodo Merge users:
| Feature | Description | | Feature | Description |
|---------|-------------| |---------------------------------------------------------------------------------------|-------------|
| [**Custom Prompt Suggestions**](https://qodo-merge-docs.qodo.ai/tools/custom_prompt/) | Generate code suggestions based on custom prompts from the user | | [**Custom Prompt Suggestions**](https://qodo-merge-docs.qodo.ai/tools/custom_prompt/) | Generate code suggestions based on custom prompts from the user |
| [**Analyze PR components**](https://qodo-merge-docs.qodo.ai/tools/analyze/) | Identify the components that changed in the PR, and enable to interactively apply different tools to them | | [**Analyze PR components**](https://qodo-merge-docs.qodo.ai/tools/analyze/) | Identify the components that changed in the PR, and enable to interactively apply different tools to them |
| [**Tests**](https://qodo-merge-docs.qodo.ai/tools/test/) | Generate tests for code components that changed in the PR | | [**Tests**](https://qodo-merge-docs.qodo.ai/tools/test/) | Generate tests for code components that changed in the PR |
| [**PR documentation**](https://qodo-merge-docs.qodo.ai/tools/documentation/) | Generate docstring for code components that changed in the PR | | [**PR documentation**](https://qodo-merge-docs.qodo.ai/tools/documentation/) | Generate docstring for code components that changed in the PR |
| [**Improve Component**](https://qodo-merge-docs.qodo.ai/tools/improve_component/) | Generate code suggestions for code components that changed in the PR | | [**Improve Component**](https://qodo-merge-docs.qodo.ai/tools/improve_component/) | Generate code suggestions for code components that changed in the PR |
| [**Similar code search**](https://qodo-merge-docs.qodo.ai/tools/similar_code/) | Search for similar code in the repository, organization, or entire GitHub | | [**Similar code search**](https://qodo-merge-docs.qodo.ai/tools/similar_code/) | Search for similar code in the repository, organization, or entire GitHub |
| [**Code implementation**](https://qodo-merge-docs.qodo.ai/tools/implement/) | Generates implementation code from review suggestions |
### Supported languages ### Supported languages
Qodo Merge Pro leverages the world's leading code models - Claude 3.5 Sonnet and GPT-4. Qodo Merge 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. 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). For specialized commands that require static code analysis, Qodo Merge 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).

View File

@ -14,6 +14,5 @@ An example result:
![Analyze 1](https://codium.ai/images/pr_agent/analyze_1.png){width=750} ![Analyze 1](https://codium.ai/images/pr_agent/analyze_1.png){width=750}
**Notes** !!! note "Language that are currently supported:"
Python, Java, C++, JavaScript, TypeScript, C#.
- Language that are currently supported: Python, Java, C++, JavaScript, TypeScript, C#.

View File

@ -38,20 +38,20 @@ where `https://real_link_to_image` is the direct link to the image.
Note that GitHub has a built-in mechanism of pasting images in comments. However, pasted image does not provide a direct link. Note that GitHub has a built-in mechanism of pasting images in comments. However, pasted image does not provide a direct link.
To get a direct link to an image, we recommend using the following scheme: To get a direct link to an image, we recommend using the following scheme:
1) First, post a comment that contains **only** the image: 1\. First, post a comment that contains **only** the image:
![Ask image1](https://codium.ai/images/pr_agent/ask_images1.png){width=512} ![Ask image1](https://codium.ai/images/pr_agent/ask_images1.png){width=512}
2) Quote reply to that comment: 2\. Quote reply to that comment:
![Ask image2](https://codium.ai/images/pr_agent/ask_images2.png){width=512} ![Ask image2](https://codium.ai/images/pr_agent/ask_images2.png){width=512}
3) In the screen opened, type the question below the image: 3\. In the screen opened, type the question below the image:
![Ask image3](https://codium.ai/images/pr_agent/ask_images3.png){width=512} ![Ask image3](https://codium.ai/images/pr_agent/ask_images3.png){width=512}
![Ask image4](https://codium.ai/images/pr_agent/ask_images4.png){width=512} ![Ask image4](https://codium.ai/images/pr_agent/ask_images4.png){width=512}
4) Post the comment, and receive the answer: 4\. Post the comment, and receive the answer:
![Ask image5](https://codium.ai/images/pr_agent/ask_images5.png){width=512} ![Ask image5](https://codium.ai/images/pr_agent/ask_images5.png){width=512}

View File

@ -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. 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 💎 #### 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
* GitHub : `https://github.com/{owner}/{repo}/labels`, or click on the "Labels" tab in the issues or PRs page. * 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. * GitLab : `https://gitlab.com/{owner}/{repo}/-/labels`, or click on "Manage" -> "Labels" on the left menu.

View File

@ -51,8 +51,8 @@ Results obtained with the prompt above:
## Configuration options ## Configuration options
`prompt`: the prompt for the tool. It should be a multi-line string. - `prompt`: the prompt for the tool. It should be a multi-line string.
`num_code_suggestions`: number of code suggestions provided by the 'custom_prompt' tool. Default is 4. - `num_code_suggestions_per_chunk`: number of code suggestions provided by the 'custom_prompt' tool, per chunk. Default is 4.
`enable_help_text`: if set to true, the tool will display a help text in the comment. Default is true. - `enable_help_text`: if set to true, the tool will display a help text in the comment. Default is true.

View File

@ -143,7 +143,7 @@ The marker `pr_agent:type` will be replaced with the PR type, `pr_agent:summary`
![Describe markers before](https://codium.ai/images/pr_agent/describe_markers_before.png){width=512} ![Describe markers before](https://codium.ai/images/pr_agent/describe_markers_before.png){width=512}
&rarr; becomes
![Describe markers after](https://codium.ai/images/pr_agent/describe_markers_after.png){width=512} ![Describe markers after](https://codium.ai/images/pr_agent/describe_markers_after.png){width=512}

View File

@ -27,7 +27,6 @@ You can state a name of a specific component in the PR to get documentation only
- `docs_style`: The exact style of the documentation (for python docstring). you can choose between: `google`, `numpy`, `sphinx`, `restructuredtext`, `plain`. Default is `sphinx`. - `docs_style`: The exact style of the documentation (for python docstring). you can choose between: `google`, `numpy`, `sphinx`, `restructuredtext`, `plain`. Default is `sphinx`.
- `extra_instructions`: Optional extra instructions to the tool. For example: "focus on the changes in the file X. Ignore change in ...". - `extra_instructions`: Optional extra instructions to the tool. For example: "focus on the changes in the file X. Ignore change in ...".
**Notes** !!! note "Notes"
- The following languages are currently supported: Python, Java, C++, JavaScript, TypeScript, C#.
- 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.
- This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool.

View File

@ -1,6 +1,6 @@
## Overview ## Overview
The `help` tool provides a list of all the available tools and their descriptions. The `help` tool provides a list of all the available tools and their descriptions.
For Qodo Merge Pro users, it also enables to trigger each tool by checking the relevant box. For Qodo Merge users, it also enables to trigger each tool by checking the relevant box.
It can be invoked manually by commenting on any PR: It can be invoked manually by commenting on any PR:
``` ```

View File

@ -0,0 +1,54 @@
`Platforms supported: GitHub, GitLab, Bitbucket`
## Overview
The `implement` tool converts human code review discussions and feedback into ready-to-commit code changes.
It leverages LLM technology to transform PR comments and review suggestions into concrete implementation code, helping developers quickly turn feedback into working solutions.
## Usage Scenarios
### For Reviewers
Reviewers can request code changes by:
1. Selecting the code block to be modified.
2. Adding a comment with the syntax:
```
/implement <code-change-description>
```
![implement1](https://codium.ai/images/pr_agent/implement1.png){width=640}
### For PR Authors
PR authors can implement suggested changes by replying to a review comment using either: <br>
1. Add specific implementation details as described above
```
/implement <code-change-description>
```
2. Use the original review comment as instructions
```
/implement
```
![implement2](https://codium.ai/images/pr_agent/implement2.png){width=640}
### For Referencing Comments
You can reference and implement changes from any comment by:
```
/implement <link-to-review-comment>
```
![implement3](https://codium.ai/images/pr_agent/implement3.png){width=640}
Note that the implementation will occur within the review discussion thread.
**Configuration options**
- Use `/implement` to implement code change within and based on the review discussion.
- Use `/implement <code-change-description>` inside a review discussion to implement specific instructions.
- Use `/implement <link-to-review-comment>` to indirectly call the tool from any comment.

View File

@ -9,8 +9,9 @@ The tool can be triggered automatically every time a new PR is [opened](../usage
![code_suggestions_as_comment_open.png](https://codium.ai/images/pr_agent/code_suggestions_as_comment_open.png){width=512} ![code_suggestions_as_comment_open.png](https://codium.ai/images/pr_agent/code_suggestions_as_comment_open.png){width=512}
Note that the `Apply this suggestion` checkbox, which interactively converts a suggestion into a commitable code comment, is available only for Qodo Merge Pro 💎 users. !!! note "The following features are available only for Qodo Merge 💎 users:"
- The `Apply this suggestion` checkbox, which interactively converts a suggestion into a committable code comment
- The `More` checkbox to generate additional suggestions
## Example usage ## Example usage
@ -52,9 +53,10 @@ num_code_suggestions_per_chunk = ...
- The `pr_commands` lists commands that will be executed automatically when a PR is opened. - The `pr_commands` lists commands that will be executed automatically when a PR is opened.
- The `[pr_code_suggestions]` section contains the configurations for the `improve` tool you want to edit (if any) - The `[pr_code_suggestions]` section contains the configurations for the `improve` tool you want to edit (if any)
### Assessing Impact 💎 ### Assessing Impact
>`💎 feature`
Note that Qodo Merge pro tracks two types of implementations: Qodo Merge tracks two types of implementations for tracking implemented suggestions:
- Direct implementation - when the user directly applies the suggestion by clicking the `Apply` checkbox. - Direct implementation - when the user directly applies the suggestion by clicking the `Apply` checkbox.
- Indirect implementation - when the user implements the suggestion in their IDE environment. In this case, Qodo Merge will utilize, after each commit, a dedicated logic to identify if a suggestion was implemented, and will mark it as implemented. - Indirect implementation - when the user implements the suggestion in their IDE environment. In this case, Qodo Merge will utilize, after each commit, a dedicated logic to identify if a suggestion was implemented, and will mark it as implemented.
@ -67,10 +69,10 @@ In post-process, Qodo Merge counts the number of suggestions that were implement
![code_suggestions_asses_impact_stats_2](https://codium.ai/images/pr_agent/code_suggestions_asses_impact_stats_2.png){width=512} ![code_suggestions_asses_impact_stats_2](https://codium.ai/images/pr_agent/code_suggestions_asses_impact_stats_2.png){width=512}
## Suggestion tracking 💎 ## Suggestion tracking
`Platforms supported: GitHub, GitLab` >`💎 feature. Platforms supported: GitHub, GitLab`
Qodo Merge employs an novel detection system to automatically [identify](https://qodo-merge-docs.qodo.ai/core-abilities/impact_evaluation/) AI code suggestions that PR authors have accepted and implemented. Qodo Merge employs a novel detection system to automatically [identify](https://qodo-merge-docs.qodo.ai/core-abilities/impact_evaluation/) AI code suggestions that PR authors have accepted and implemented.
Accepted suggestions are also automatically documented in a dedicated wiki page called `.pr_agent_accepted_suggestions`, allowing users to track historical changes, assess the tool's effectiveness, and learn from previously implemented recommendations in the repository. Accepted suggestions are also automatically documented in a dedicated wiki page called `.pr_agent_accepted_suggestions`, allowing users to track historical changes, assess the tool's effectiveness, and learn from previously implemented recommendations in the repository.
An example [result](https://github.com/Codium-ai/pr-agent/wiki/.pr_agent_accepted_suggestions): An example [result](https://github.com/Codium-ai/pr-agent/wiki/.pr_agent_accepted_suggestions):
@ -95,6 +97,147 @@ This feature is controlled by a boolean configuration parameter: `pr_code_sugges
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. 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.
## `Extra instructions` and `best practices`
The `improve` tool can be further customized by providing additional instructions and best practices to the AI model.
### Extra instructions
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.
Examples for possible instructions:
```toml
[pr_code_suggestions]
extra_instructions="""\
(1) Answer in japanese
(2) Don't suggest to add try-except block
(3) Ignore changes in toml files
...
"""
```
Use triple quotes to write multi-line instructions. Use bullet points or numbers to make the instructions more readable.
### Best practices
> `💎 feature. Platforms supported: GitHub, GitLab, Bitbucket`
Another option to give additional guidance to the AI model is by creating a `best_practices.md` file, either in your repository's root directory or as a [**wiki page**](https://github.com/Codium-ai/pr-agent/wiki) (we recommend the wiki page, as editing and maintaining it over time is easier).
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 create additional suggestions, with a dedicated label: `Organization
best practice`.
Example for a python `best_practices.md` content:
```markdown
## Project best practices
- Make sure that I/O operations are encapsulated in a try-except block
- Use the `logging` module for logging instead of `print` statements
- Use `is` and `is not` to compare with `None`
- Use `if __name__ == '__main__':` to run the code only when the script is executed
- Use `with` statement to open files
...
```
Tips for writing an effective `best_practices.md` file:
- Write clearly and concisely
- Include brief code examples when helpful
- Focus on project-specific guidelines, that will result in relevant suggestions you actually want to get
- Keep the file relatively short, under 800 lines, since:
- AI models may not process effectively very long documents
- Long files tend to contain generic guidelines already known to AI
#### Local and global best practices
By default, Qodo Merge will look for a local `best_practices.md` wiki file in the root of the relevant local repo.
If you want to enable also a global `best_practices.md` wiki file, set first in the global configuration file:
```toml
[best_practices]
enable_global_best_practices = true
```
Then, create a `best_practices.md` wiki file in the root of [global](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/#global-configuration-file) configuration repository, `pr-agent-settings`.
#### Best practices for multiple languages
For a git organization working with multiple programming languages, you can maintain a centralized global `best_practices.md` file containing language-specific guidelines.
When reviewing pull requests, Qodo Merge automatically identifies the programming language and applies the relevant best practices from this file.
To do this, structure your `best_practices.md` file using the following format:
```
# [Python]
...
# [Java]
...
# [JavaScript]
...
```
#### Dedicated label for best practices suggestions
Best practice suggestions are labeled as `Organization best practice` by default.
To customize this label, modify it in your configuration file:
```toml
[best_practices]
organization_name = "..."
```
And the label will be: `{organization_name} best practice`.
#### Example results
![best_practice](https://codium.ai/images/pr_agent/org_best_practice.png){width=512}
### Auto best practices
>`💎 feature. Platforms supported: GitHub.`
`Auto best practices` is a novel Qodo Merge capability that:
1. Identifies recurring patterns from accepted suggestions
2. **Automatically** generates [best practices page](https://github.com/qodo-ai/pr-agent/wiki/.pr_agent_auto_best_practices) based on what your team consistently values
3. Applies these learned patterns to future code reviews
This creates an automatic feedback loop where the system continuously learns from your team's choices to provide increasingly relevant suggestions.
The system maintains two analysis phases:
- Open exploration for new issues
- Targeted checking against established best practices
Note that when a [custom best practices](https://qodo-merge-docs.qodo.ai/tools/improve/#best-practices) exist, Qodo Merge will still generate an 'auto best practices' wiki file, though it won't use it in the `improve` tool.
Learn more about utilizing 'auto best practices' in our [detailed guide](https://qodo-merge-docs.qodo.ai/core-abilities/auto_best_practices/).
#### Relevant configurations
```toml
[auto_best_practices]
# Disable all auto best practices usage or generation
enable_auto_best_practices = true
# Disable usage of auto best practices file in the 'improve' tool
utilize_auto_best_practices = true
# Extra instructions to the auto best practices generation prompt
extra_instructions = ""
# Max number of patterns to be detected
max_patterns = 5
```
### Combining 'extra instructions' and 'best practices'
> `💎 feature`
The `extra instructions` configuration is more related to the `improve` tool prompt. It can be used, for example, to avoid specific suggestions ("Don't suggest to add try-except block", "Ignore changes in toml files", ...) or to emphasize specific aspects or formats ("Answer in Japanese", "Give only short suggestions", ...)
In contrast, the `best_practices.md` file is a general guideline for the way code should be written in the repo.
Using a combination of both can help the AI model to provide relevant and tailored suggestions.
## Usage Tips ## Usage Tips
### Implementing the proposed code suggestions ### Implementing the proposed code suggestions
@ -125,6 +268,8 @@ dual_publishing_score_threshold = x
Where x represents the minimum score threshold (>=) for suggestions to be presented as commitable PR comments in addition to the table. Default is -1 (disabled). Where x represents the minimum score threshold (>=) for suggestions to be presented as commitable PR comments in addition to the table. Default is -1 (disabled).
### Self-review ### Self-review
> `💎 feature`
If you set in a configuration file: If you set in a configuration file:
```toml ```toml
[pr_code_suggestions] [pr_code_suggestions]
@ -168,21 +313,56 @@ code_suggestions_self_review_text = "... (your text here) ..."
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. 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.
### Auto-approval
> `💎 feature. Platforms supported: GitHub, GitLab, Bitbucket`
Under specific conditions, Qodo Merge can auto-approve a PR when a specific comment is invoked, or when the PR meets certain criteria.
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:
```toml
[config]
enable_auto_approval = true
```
Note that this specific flag cannot be set with a command line argument, only in the configuration file, committed to the repository.
This ensures that enabling auto-approval is a deliberate decision by the repository owner.
**(1) Auto-approval by commenting**
After enabling, by commenting on a PR:
```
/review auto_approve
```
Qodo Merge will automatically approve the PR, and add a comment with the approval.
**(2) Auto-approval when the PR meets certain criteria**
There are two criteria that can be set for auto-approval:
- **Review effort score**
```toml
[config]
auto_approve_for_low_review_effort = X # X is a number between 1 to 5
```
When the [review effort score](https://www.qodo.ai/images/pr_agent/review3.png) is lower or equal to X, the PR will be auto-approved.
___
- **No code suggestions**
```toml
[config]
auto_approve_for_no_suggestions = true
```
When no [code suggestion](https://www.qodo.ai/images/pr_agent/code_suggestions_as_comment_closed.png) were found for the PR, the PR will be auto-approved.
### How many code suggestions are generated? ### 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: Qodo Merge uses a dynamic strategy to generate code suggestions based on the size of the pull request (PR). Here's how it works:
1) Chunking large PRs: #### 1. Chunking large PRs
- Qodo Merge divides large PRs into 'chunks'. - Qodo Merge divides large PRs into 'chunks'.
- Each chunk contains up to `pr_code_suggestions.max_context_tokens` tokens (default: 14,000). - Each chunk contains up to `pr_code_suggestions.max_context_tokens` tokens (default: 14,000).
#### 2. Generating suggestions
2) Generating suggestions:
- For each chunk, Qodo Merge generates up to `pr_code_suggestions.num_code_suggestions_per_chunk` suggestions (default: 4). - For each chunk, Qodo Merge generates up to `pr_code_suggestions.num_code_suggestions_per_chunk` suggestions (default: 4).
This approach has two main benefits: This approach has two main benefits:
- Scalability: The number of suggestions scales with the PR size, rather than being fixed. - Scalability: The number of suggestions scales with the PR size, rather than being fixed.
@ -191,73 +371,6 @@ This approach has two main benefits:
Note: Chunking is primarily relevant for large PRs. For most PRs (up to 500 lines of code), Qodo Merge will be able to process the entire code in a single call. Note: Chunking is primarily relevant for large PRs. For most PRs (up to 500 lines of code), Qodo Merge will be able to process the entire code in a single call.
### 'Extra instructions' and 'best practices'
#### Extra instructions
>`Platforms supported: GitHub, GitLab, Bitbucket`
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]
extra_instructions="""\
(1) Answer in japanese
(2) Don't suggest to add try-excpet block
(3) Ignore changes in toml files
...
"""
```
Use triple quotes to write multi-line instructions. Use bullet points or numbers to make the instructions more readable.
#### Best practices 💎
>`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`.
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`.
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:
- It should be written in a clear and concise manner
- If needed, it should give short relevant code snippets as examples
- Recommended to limit the text to 800 lines or fewer. Heres 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
By default, Qodo Merge will look for a local `best_practices.md` wiki file in the root of the relevant local repo.
If you want to enable also a global `best_practices.md` wiki file, set first in the global configuration file:
```toml
[best_practices]
enable_global_best_practices = true
```
Then, create a `best_practices.md` wiki file in the root of [global](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/#global-configuration-file) configuration repository, `pr-agent-settings`.
##### Example results
![best_practice](https://codium.ai/images/pr_agent/org_best_practice.png){width=512}
#### How to combine `extra instructions` and `best practices`
The `extra instructions` configuration is more related to the `improve` tool prompt. It can be used, for example, to avoid specific suggestions ("Don't suggest to add try-except block", "Ignore changes in toml files", ...) or to emphasize specific aspects or formats ("Answer in Japanese", "Give only short suggestions", ...)
In contrast, the `best_practices.md` file is a general guideline for the way code should be written in the repo.
Using a combination of both can help the AI model to provide relevant and tailored suggestions.
## Configuration options ## Configuration options
??? example "General options" ??? example "General options"
@ -276,12 +389,12 @@ Using a combination of both can help the AI model to provide relevant and tailor
<td>Minimum score threshold for suggestions to be presented as commitable PR comments in addition to the table. Default is -1 (disabled).</td> <td>Minimum score threshold for suggestions to be presented as commitable PR comments in addition to the table. Default is -1 (disabled).</td>
</tr> </tr>
<tr> <tr>
<td><b>persistent_comment</b></td> <td><b>focus_only_on_problems</b></td>
<td>If set to true, the improve comment will be persistent, meaning that every new improve request will edit the previous one. Default is false.</td> <td>If set to true, suggestions will focus primarily on identifying and fixing code problems, and less on style considerations like best practices, maintainability, or readability. Default is true.</td>
</tr> </tr>
<tr> <tr>
<td><b>self_reflect_on_suggestions</b></td> <td><b>persistent_comment</b></td>
<td>If set to true, the improve tool will calculate an importance score for each suggestion [1-10], and sort the suggestion labels group based on this score. Default is true.</td> <td>If set to true, the improve comment will be persistent, meaning that every new improve request will edit the previous one. Default is false.</td>
</tr> </tr>
<tr> <tr>
<td><b>suggestions_score_threshold</b></td> <td><b>suggestions_score_threshold</b></td>
@ -291,6 +404,10 @@ Using a combination of both can help the AI model to provide relevant and tailor
<td><b>apply_suggestions_checkbox</b></td> <td><b>apply_suggestions_checkbox</b></td>
<td> Enable the checkbox to create a committable suggestion. Default is true.</td> <td> Enable the checkbox to create a committable suggestion. Default is true.</td>
</tr> </tr>
<tr>
<td><b>enable_more_suggestions_checkbox</b></td>
<td> Enable the checkbox to generate more suggestions. Default is true.</td>
</tr>
<tr> <tr>
<td><b>enable_help_text</b></td> <td><b>enable_help_text</b></td>
<td>If set to true, the tool will display a help text in the comment. Default is true.</td> <td>If set to true, the tool will display a help text in the comment. Default is true.</td>
@ -303,6 +420,10 @@ Using a combination of both can help the AI model to provide relevant and tailor
<td><b>wiki_page_accepted_suggestions</b></td> <td><b>wiki_page_accepted_suggestions</b></td>
<td>If set to true, the tool will automatically track accepted suggestions in a dedicated wiki page called `.pr_agent_accepted_suggestions`. Default is true.</td> <td>If set to true, the tool will automatically track accepted suggestions in a dedicated wiki page called `.pr_agent_accepted_suggestions`. Default is true.</td>
</tr> </tr>
<tr>
<td><b>allow_thumbs_up_down</b></td>
<td>If set to true, all code suggestions will have thumbs up and thumbs down buttons, to encourage users to provide feedback on the suggestions. Default is false.</td>
</tr>
</table> </table>
??? example "Params for number of suggestions and AI calls" ??? example "Params for number of suggestions and AI calls"
@ -320,10 +441,6 @@ Using a combination of both can help the AI model to provide relevant and tailor
<td><b>max_number_of_calls</b></td> <td><b>max_number_of_calls</b></td>
<td>Maximum number of chunks. Default is 3.</td> <td>Maximum number of chunks. Default is 3.</td>
</tr> </tr>
<tr>
<td><b>rank_extended_suggestions</b></td>
<td>If set to true, the tool will rank the suggestions, based on importance. Default is true.</td>
</tr>
</table> </table>
## A note on code suggestions quality ## A note on code suggestions quality

View File

@ -18,9 +18,9 @@ The tool will generate code suggestions for the selected component (if no compon
![improve_component2](https://codium.ai/images/pr_agent/improve_component2.png){width=768} ![improve_component2](https://codium.ai/images/pr_agent/improve_component2.png){width=768}
**Notes** !!! note "Notes"
- Language that are currently supported by the tool: Python, Java, C++, JavaScript, TypeScript, C#. - Language that are currently supported by the tool: Python, Java, C++, JavaScript, TypeScript, C#.
- This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool. - This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool.
## Configuration options ## Configuration options
- `num_code_suggestions`: number of code suggestions to provide. Default is 4 - `num_code_suggestions`: number of code suggestions to provide. Default is 4

View File

@ -3,7 +3,7 @@
Here is a list of Qodo Merge tools, each with a dedicated page that explains how to use it: Here is a list of Qodo Merge tools, each with a dedicated page that explains how to use it:
| Tool | Description | | Tool | Description |
|------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------| |------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| **[PR Description (`/describe`](./describe.md))** | Automatically generating PR description - title, type, summary, code walkthrough and labels | | **[PR Description (`/describe`](./describe.md))** | Automatically generating PR description - title, type, summary, code walkthrough and labels |
| **[PR Review (`/review`](./review.md))** | Adjustable feedback about the PR, possible issues, security concerns, review effort and more | | **[PR Review (`/review`](./review.md))** | Adjustable feedback about the PR, possible issues, security concerns, review effort and more |
| **[Code Suggestions (`/improve`](./improve.md))** | Code suggestions for improving the PR | | **[Code Suggestions (`/improve`](./improve.md))** | Code suggestions for improving the PR |
@ -13,10 +13,11 @@ Here is a list of Qodo Merge tools, each with a dedicated page that explains how
| **[Help (`/help`](./help.md))** | Provides a list of all the available tools. Also enables to trigger them interactively (💎) | | **[Help (`/help`](./help.md))** | Provides a list of all the available tools. Also enables to trigger them interactively (💎) |
| **💎 [Add Documentation (`/add_docs`](./documentation.md))** | Generates documentation to methods/functions/classes that changed in the PR | | **💎 [Add Documentation (`/add_docs`](./documentation.md))** | Generates documentation to methods/functions/classes that changed in the PR |
| **💎 [Generate Custom Labels (`/generate_labels`](./custom_labels.md))** | Generates custom labels for the PR, based on specific guidelines defined by the user | | **💎 [Generate Custom Labels (`/generate_labels`](./custom_labels.md))** | Generates custom labels for the PR, based on specific guidelines defined by the user |
| **💎 [Analyze (`/analyze`](./analyze.md))** | Identify code components that changed in the PR, and enables to interactively generate tests, docs, and code suggestions for each component | | **💎 [Analyze (`/analyze`](./analyze.md))** | Identify code components that changed in the PR, and enables to interactively generate tests, docs, and code suggestions for each component|
| **💎 [Test (`/test`](./test.md))** | generate tests for a selected component, based on the PR code changes |
| **💎 [Custom Prompt (`/custom_prompt`](./custom_prompt.md))** | Automatically generates custom suggestions for improving the PR code, based on specific guidelines defined by the user | | **💎 [Custom Prompt (`/custom_prompt`](./custom_prompt.md))** | Automatically generates custom suggestions for improving the PR code, based on specific guidelines defined by the user |
| **💎 [Generate Tests (`/test component_name`](./test.md))** | Automatically generates unit tests for a selected component, based on the PR code changes | | **💎 [Generate Tests (`/test component_name`](./test.md))** | Automatically generates unit tests for a selected component, based on the PR code changes |
| **💎 [Improve Component (`/improve_component component_name`](./improve_component.md))** | Generates code suggestions for a specific code component that changed in the PR | | **💎 [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 | | **💎 [CI Feedback (`/checks ci_job`](./ci_feedback.md))** | Automatically generates feedback and analysis for a failed CI job |
| **💎 [Implement (`/implement`](./implement.md))** | Generates implementation code from review suggestions |
Note that the tools marked with 💎 are available only for Qodo Merge Pro users. Note that the tools marked with 💎 are available only for Qodo Merge users.

View File

@ -39,72 +39,27 @@ pr_commands = [
] ]
[pr_reviewer] [pr_reviewer]
num_code_suggestions = ... extra_instructions = "..."
... ...
``` ```
- The `pr_commands` lists commands that will be executed automatically when a PR is opened. - The `pr_commands` lists commands that will be executed automatically when a PR is opened.
- The `[pr_reviewer]` section contains the configurations for the `review` tool you want to edit (if any). - The `[pr_reviewer]` section contains the configurations for the `review` tool you want to edit (if any).
[//]: # ()
[//]: # (### Incremental Mode)
[//]: # (Incremental review only considers changes since the last Qodo Merge review. This can be useful when working on the PR in an iterative manner, and you want to focus on the changes since the last review instead of reviewing the entire PR again.)
[//]: # (For invoking the incremental mode, the following command can be used:)
[//]: # (```)
[//]: # (/review -i)
[//]: # (```)
[//]: # (Note that the incremental mode is only available for GitHub.)
[//]: # ()
[//]: # (![incremental review]&#40;https://codium.ai/images/pr_agent/incremental_review_2.png&#41;{width=512})
[//]: # (### PR Reflection)
[//]: # ()
[//]: # (By invoking:)
[//]: # (```)
[//]: # (/reflect_and_review)
[//]: # (```)
[//]: # (The tool will first ask the author questions about the PR, and will guide the review based on their answers.)
[//]: # ()
[//]: # (![reflection questions]&#40;https://codium.ai/images/pr_agent/reflection_questions.png&#41;{width=512})
[//]: # ()
[//]: # (![reflection answers]&#40;https://codium.ai/images/pr_agent/reflection_answers.png&#41;{width=512})
[//]: # ()
[//]: # (![reflection insights]&#40;https://codium.ai/images/pr_agent/reflection_insights.png&#41;{width=512})
## Configuration options ## Configuration options
!!! example "General options" !!! example "General options"
<table> <table>
<tr>
<td><b>num_code_suggestions</b></td>
<td>Number of code suggestions provided by the 'review' tool. Default is 0, meaning no code suggestions will be provided by the `review` tool.</td>
</tr>
<tr>
<td><b>inline_code_comments</b></td>
<td>If set to true, the tool will publish the code suggestions as comments on the code diff. Default is false. Note that you need to set `num_code_suggestions`>0 to get code suggestions </td>
</tr>
<tr> <tr>
<td><b>persistent_comment</b></td> <td><b>persistent_comment</b></td>
<td>If set to true, the review comment will be persistent, meaning that every new review request will edit the previous one. Default is true.</td> <td>If set to true, the review comment will be persistent, meaning that every new review request will edit the previous one. Default is true.</td>
</tr> </tr>
<tr>
<td><b>final_update_message</b></td>
<td>When set to true, updating a persistent review comment during online commenting will automatically add a short comment with a link to the updated review in the pull request .Default is true.</td>
</tr>
<tr> <tr>
<td><b>extra_instructions</b></td> <td><b>extra_instructions</b></td>
<td>Optional extra instructions to the tool. For example: "focus on the changes in the file X. Ignore change in ...".</td> <td>Optional extra instructions to the tool. For example: "focus on the changes in the file X. Ignore change in ...".</td>
@ -140,7 +95,7 @@ num_code_suggestions = ...
</tr> </tr>
<tr> <tr>
<td><b>require_ticket_analysis_review</b></td> <td><b>require_ticket_analysis_review</b></td>
<td>If set to true, and the PR contains a GitHub ticket number, the tool will add a section that checks if the PR in fact fulfilled the ticket requirements. Default is true.</td> <td>If set to true, and the PR contains a GitHub or Jira ticket link, the tool will add a section that checks if the PR in fact fulfilled the ticket requirements. Default is true.</td>
</tr> </tr>
</table> </table>
@ -159,20 +114,6 @@ You can enable\disable the `review` tool to add specific labels to the PR:
</tr> </tr>
</table> </table>
!!! example "Auto-approval"
If enabled, the `review` tool can approve a PR when a specific comment, `/review auto_approve`, is invoked.
<table>
<tr>
<td><b>enable_auto_approval</b></td>
<td>If set to true, the tool will approve the PR when invoked with the 'auto_approve' command. Default is false. This flag can be changed only from a configuration file.</td>
</tr>
<tr>
<td><b>maximal_review_effort</b></td>
<td>Maximal effort level for auto-approval. If the PR's estimated review effort is above this threshold, the auto-approval will not run. Default is 5.</td>
</tr>
</table>
## Usage Tips ## Usage Tips
@ -189,9 +130,9 @@ If enabled, the `review` tool can approve a PR when a specific comment, `/review
!!! tip "Automation" !!! tip "Automation"
When you first install Qodo Merge app, the [default mode](../usage-guide/automations_and_usage.md#github-app-automatic-tools-when-a-new-pr-is-opened) for the `review` tool is: When you first install Qodo Merge app, the [default mode](../usage-guide/automations_and_usage.md#github-app-automatic-tools-when-a-new-pr-is-opened) for the `review` tool is:
``` ```
pr_commands = ["/review --pr_reviewer.num_code_suggestions=0", ...] pr_commands = ["/review", ...]
``` ```
Meaning the `review` tool will run automatically on every PR, without providing code suggestions. Meaning the `review` tool will run automatically on every PR, without any additional configurations.
Edit this field to enable/disable the tool, or to change the configurations used. Edit this field to enable/disable the tool, or to change the configurations used.
!!! tip "Possible labels from the review tool" !!! tip "Possible labels from the review tool"
@ -224,38 +165,10 @@ If enabled, the `review` tool can approve a PR when a specific comment, `/review
Use triple quotes to write multi-line instructions. Use bullet points to make the instructions more readable. Use triple quotes to write multi-line instructions. Use bullet points to make the instructions more readable.
!!! 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: !!! tip "Code suggestions"
```
/review auto_approve The `review` tool previously included a legacy feature for providing code suggestions (controlled by `--pr_reviewer.num_code_suggestion`). This functionality has been deprecated and replaced by the [`improve`](./improve.md) tool, which offers higher quality and more actionable code suggestions.
```
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]
maximal_review_effort = 5
```
[//]: # (!!! tip "Code suggestions")
[//]: # ()
[//]: # ( If you set `num_code_suggestions`>0 , the `review` tool will also provide code suggestions.)
[//]: # ( )
[//]: # ( Notice If you are interested **only** in the code suggestions, it is recommended to use the [`improve`]&#40;./improve.md&#41; 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.)

View File

@ -49,9 +49,10 @@ It can be invoked automatically from the analyze table, can be accessed by:
/analyze /analyze
``` ```
Choose the components you want to find similar code for, and click on the `similar` checkbox. 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} ![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. You can search for similar code either within the organization's codebase or globally, which includes open-source repositories. Each result will include the relevant code components along with their associated license details.
![similar code global](https://codium.ai/images/pr_agent/similar_code_global.png){width=768} ![similar code global](https://codium.ai/images/pr_agent/similar_code_global.png){width=768}

View File

@ -16,14 +16,17 @@ 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). Note that to perform retrieval, the `similar_issue` tool indexes all the repo previous issues (once).
### Selecting a Vector Database
Configure your preferred database by changing the `pr_similar_issue` parameter in `configuration.toml` file.
**Select VectorDBs** by changing `pr_similar_issue` parameter in `configuration.toml` file #### Available Options
Choose from the following Vector Databases:
2 VectorDBs are available to switch in
1. LanceDB 1. LanceDB
2. Pinecone 2. Pinecone
To enable usage of the '**similar issue**' tool for Pinecone, you need to set the following keys in `.secrets.toml` (or in the relevant environment variables): #### Pinecone Configuration
To use Pinecone with the `similar issue` tool, add these credentials to `.secrets.toml` (or set as environment variables):
``` ```
[pinecone] [pinecone]

View File

@ -17,9 +17,9 @@ The tool will generate tests for the selected component (if no component is stat
(Example taken from [here](https://github.com/Codium-ai/pr-agent/pull/598#issuecomment-1913679429)): (Example taken from [here](https://github.com/Codium-ai/pr-agent/pull/598#issuecomment-1913679429)):
**Notes** !!! note "Notes"
- Language that are currently supported by the tool: Python, Java, C++, JavaScript, TypeScript, C#. - The following languages are currently supported: Python, Java, C++, JavaScript, TypeScript, C#.
- This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool. - This tool can also be triggered interactively by using the [`analyze`](./analyze.md) tool.
## Configuration options ## Configuration options

View File

@ -17,3 +17,4 @@ Under the section `pr_update_changelog`, the [configuration file](https://github
- `push_changelog_changes`: whether to push the changes to CHANGELOG.md, or just print them. Default is false (print only). - `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 ... - `extra_instructions`: Optional extra instructions to the tool. For example: "focus on the changes in the file X. Ignore change in ...
- `add_pr_link`: whether the model should try to add a link to the PR in the changelog. Default is true.

View File

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

View File

@ -1,5 +1,5 @@
## Show possible configurations ## Show possible configurations
The possible configurations of Qodo Merge are stored in [here](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml). The possible configurations of Qodo Merge are stored in [here](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml){:target="_blank"}.
In the [tools](https://qodo-merge-docs.qodo.ai/tools/) page you can find explanations on how to use these configurations for each tool. In the [tools](https://qodo-merge-docs.qodo.ai/tools/) page you can find explanations on how to use these configurations for each tool.
To print all the available configurations as a comment on your PR, you can use the following command: To print all the available configurations as a comment on your PR, you can use the following command:
@ -57,6 +57,23 @@ All Qodo Merge tools have a parameter called `extra_instructions`, that enables
/update_changelog --pr_update_changelog.extra_instructions="Make sure to update also the version ..." /update_changelog --pr_update_changelog.extra_instructions="Make sure to update also the version ..."
``` ```
## Language Settings
The default response language for Qodo Merge is **U.S. English**. However, some development teams may prefer to display information in a different language. For example, your team's workflow might improve if PR descriptions and code suggestions are set to your country's native language.
To configure this, set the `response_language` parameter in the configuration file. This will prompt the model to respond in the specified language. Use a **standard locale code** based on [ISO 3166](https://en.wikipedia.org/wiki/ISO_3166) (country codes) and [ISO 639](https://en.wikipedia.org/wiki/ISO_639) (language codes) to define a language-country pair. See this [comprehensive list of locale codes](https://simplelocalize.io/data/locales/).
Example:
```toml
[config]
response_language: "it-IT"
```
This will set the response language globally for all the commands to Italian.
> **Important:** Note that only dynamic text generated by the AI model is translated to the configured language. Static text such as labels and table headers that are not part of the AI models response will remain in US English. In addition, the model you are using must have good support for the specified language.
## Working with large PRs ## Working with large PRs
The default mode of CodiumAI is to have a single call per tool, using GPT-4, which has a token limit of 8000 tokens. The default mode of CodiumAI is to have a single call per tool, using GPT-4, which has a token limit of 8000 tokens.
@ -138,7 +155,15 @@ LANGSMITH_BASE_URL=<url>
## Ignoring automatic commands in PRs ## Ignoring automatic commands in PRs
In some cases, you may want to automatically ignore specific PRs . Qodo Merge enables you to ignore PR with a specific title, or from/to specific branches (regex matching). Qodo Merge allows you to automatically ignore certain PRs based on various criteria:
- PRs with specific titles (using regex matching)
- PRs between specific branches (using regex matching)
- PRs not from specific folders
- PRs containing specific labels
- PRs opened by specific users
### Ignoring PRs with specific titles
To ignore PRs with a specific title such as "[Bump]: ...", you can add the following to your `configuration.toml` file: To ignore PRs with a specific title such as "[Bump]: ...", you can add the following to your `configuration.toml` file:
@ -149,6 +174,7 @@ ignore_pr_title = ["\\[Bump\\]"]
Where the `ignore_pr_title` is a list of regex patterns to match the PR title you want to ignore. Default is `ignore_pr_title = ["^\\[Auto\\]", "^Auto"]`. Where the `ignore_pr_title` is a list of regex patterns to match the PR title you want to ignore. Default is `ignore_pr_title = ["^\\[Auto\\]", "^Auto"]`.
### Ignoring PRs between specific branches
To ignore PRs from specific source or target branches, you can add the following to your `configuration.toml` file: To ignore PRs from specific source or target branches, you can add the following to your `configuration.toml` file:
@ -160,3 +186,46 @@ ignore_pr_target_branches = ["qa"]
Where the `ignore_pr_source_branches` and `ignore_pr_target_branches` are lists of regex patterns to match the source and target branches you want to ignore. Where the `ignore_pr_source_branches` and `ignore_pr_target_branches` are lists of regex patterns to match the source and target branches you want to ignore.
They are not mutually exclusive, you can use them together or separately. They are not mutually exclusive, you can use them together or separately.
### Ignoring PRs not from specific folders
To allow only specific folders (often needed in large monorepos), set:
```
[config]
allow_only_specific_folders=['folder1','folder2']
```
For the configuration above, automatic feedback will only be triggered when the PR changes include files where 'folder1' or 'folder2' is in the file path
### Ignoring PRs containing specific labels
To ignore PRs containg specific labels, you can add the following to your `configuration.toml` file:
```
[config]
ignore_pr_labels = ["do-not-merge"]
```
Where the `ignore_pr_labels` is a list of labels that when present in the PR, the PR will be ignored.
### Ignoring PRs from specific users
Qodo Merge automatically identifies and ignores pull requests created by bots using:
- GitHub's native bot detection system
- Name-based pattern matching
While this detection is robust, it may not catch all cases, particularly when:
- Bots are registered as regular user accounts
- Bot names don't match common patterns
To supplement the automatic bot detection, you can manually specify users to ignore. Add the following to your `configuration.toml` file to ignore PRs from specific users:
```
[config]
ignore_pr_authors = ["my-special-bot-user", ...]
```
Where the `ignore_pr_authors` is a list of usernames that you want to ignore.

View File

@ -1,4 +1,5 @@
## Local repo (CLI) ## Local repo (CLI)
When running from your locally cloned Qodo Merge repo (CLI), your local configuration file will be used. When running from your locally cloned Qodo Merge repo (CLI), your local configuration file will be used.
Examples of invoking the different tools via the CLI: Examples of invoking the different tools via the CLI:
@ -13,12 +14,12 @@ Examples of invoking the different tools via the CLI:
**Notes:** **Notes:**
(1) in addition to editing your local configuration file, you can also change any configuration value by adding it to the command line: 1. in addition to editing your local configuration file, you can also change any configuration value by adding it to the command line:
``` ```
python -m pr_agent.cli --pr_url=<pr_url> /review --pr_reviewer.extra_instructions="focus on the file: ..." python -m pr_agent.cli --pr_url=<pr_url> /review --pr_reviewer.extra_instructions="focus on the file: ..."
``` ```
(2) You can print results locally, without publishing them, by setting in `configuration.toml`: 2. You can print results locally, without publishing them, by setting in `configuration.toml`:
``` ```
[config] [config]
publish_output=false publish_output=false
@ -26,18 +27,33 @@ verbosity_level=2
``` ```
This is useful for debugging or experimenting with different tools. This is useful for debugging or experimenting with different tools.
(3) 3. **git provider**: The [git_provider](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L5) field in a configuration file determines the GIT provider that will be used by Qodo Merge. Currently, the following providers are supported:
`github` **(default)**, `gitlab`, `bitbucket`, `azure`, `codecommit`, `local`, and `gerrit`.
**git provider**: The [git_provider](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L5) field in a configuration file determines the GIT provider that will be used by Qodo Merge. Currently, the following providers are supported:
`
"github", "gitlab", "bitbucket", "azure", "codecommit", "local", "gerrit"
`
Default is "github".
### CLI Health Check
To verify that Qodo Merge has been configured correctly, you can run this health check command from the repository root:
### Online usage ```bash
python -m tests.health_test.main
```
If the health check passes, you will see the following output:
```
========
Health test passed successfully
========
```
At the end of the run.
Before running the health check, ensure you have:
- Configured your [LLM provider](https://qodo-merge-docs.qodo.ai/usage-guide/changing_a_model/)
- Added a valid GitHub token to your configuration file
## Online usage
Online usage means invoking Qodo Merge tools by [comments](https://github.com/Codium-ai/pr-agent/pull/229#issuecomment-1695021901) on a PR. Online usage means invoking Qodo Merge tools by [comments](https://github.com/Codium-ai/pr-agent/pull/229#issuecomment-1695021901) on a PR.
Commands for invoking the different tools via comments: Commands for invoking the different tools via comments:
@ -58,59 +74,80 @@ For example, if you want to edit the `review` tool configurations, you can run:
Any configuration value in [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml) file can be similarly edited. Comment `/config` to see the list of available configurations. Any configuration value in [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml) file can be similarly edited. Comment `/config` to see the list of available configurations.
## GitHub App ## Qodo Merge Automatic Feedback
!!! note "Configurations for Qodo Merge Pro"
Qodo Merge Pro for GitHub is an App, hosted by CodiumAI. So all the instructions below are relevant also for Qodo Merge Pro users. ### Disabling all automatic feedback
To easily disable all automatic feedback from Qodo Merge (GitHub App, GitLab Webhook, BitBucket App, Azure DevOps Webhook), set in a configuration file:
```toml
[config]
disable_auto_feedback = true
```
When this parameter is set to `true`, Qodo Merge will not run any automatic tools (like `describe`, `review`, `improve`) when a new PR is opened, or when new code is pushed to an open PR.
### GitHub App
!!! note "Configurations for Qodo Merge"
Qodo Merge for GitHub is an App, hosted by Qodo. So all the instructions below are relevant also for Qodo Merge users.
Same goes for [GitLab webhook](#gitlab-webhook) and [BitBucket App](#bitbucket-app) sections. Same goes for [GitLab webhook](#gitlab-webhook) and [BitBucket App](#bitbucket-app) sections.
### GitHub app automatic tools when a new PR is opened #### GitHub app automatic tools when a new PR is opened
The [github_app](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L108) section defines GitHub app specific configurations. The [github_app](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L220) 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. The configuration parameter `pr_commands` defines the list of tools that will be **run automatically** when a new PR is opened:
``` ```toml
[github_app] [github_app]
pr_commands = [ pr_commands = [
"/describe --pr_description.final_update_message=false", "/describe",
"/review --pr_reviewer.num_code_suggestions=0", "/review",
"/improve", "/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: For example, if your configuration file contains:
```
```toml
[pr_description] [pr_description]
generate_ai_title = true generate_ai_title = true
``` ```
Every time you run the `describe` tool, including automatic runs, the PR title will be generated by the AI.
To cancel the automatic run of all the tools, set: Every time you run the `describe` tool (including automatic runs) the PR title will be generated by the AI.
```
You can customize configurations specifically for automated runs by using the `--config_path=<value>` parameter.
For instance, to modify the `review` tool settings only for newly opened PRs, use:
```toml
[github_app] [github_app]
pr_commands = [] pr_commands = [
"/describe",
"/review --pr_reviewer.extra_instructions='focus on the file: ...'",
"/improve",
]
``` ```
### GitHub app automatic tools for push actions (commits to an open PR) #### GitHub app automatic tools for push actions (commits to an open PR)
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. 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. The configuration parameter `push_commands` defines the list of tools that will be **run automatically** when new code is pushed to the PR.
``` ```toml
[github_app] [github_app]
handle_push_trigger = true handle_push_trigger = true
push_commands = [ push_commands = [
"/describe", "/describe",
"/review --pr_reviewer.num_code_suggestions=0 --pr_reviewer.final_update_message=false", "/review",
] ]
``` ```
This means that when new code is pushed to the PR, the Qodo Merge will run the `describe` and `review` tools, with the specified parameters. This means that when new code is pushed to the PR, the Qodo Merge will run the `describe` and `review` tools, with the specified parameters.
## GitHub Action ### GitHub Action
`GitHub Action` is a different way to trigger Qodo Merge tools, and uses a different configuration mechanism than `GitHub App`.<br> `GitHub Action` is a different way to trigger Qodo Merge tools, and uses a different configuration mechanism than `GitHub App`.<br>
You can configure settings for `GitHub Action` by adding environment variables under the env section in `.github/workflows/pr_agent.yml` file. You can configure settings for `GitHub Action` by adding environment variables under the env section in `.github/workflows/pr_agent.yml` file.
Specifically, start by setting the following environment variables: Specifically, start by setting the following environment variables:
@ -121,7 +158,7 @@ Specifically, start by setting the following environment variables:
github_action_config.auto_review: "true" # enable\disable auto review github_action_config.auto_review: "true" # enable\disable auto review
github_action_config.auto_describe: "true" # enable\disable auto describe github_action_config.auto_describe: "true" # enable\disable auto describe
github_action_config.auto_improve: "true" # enable\disable auto improve github_action_config.auto_improve: "true" # enable\disable auto improve
github_action_config.pr_actions: ["opened", "reopened", "ready_for_review", "review_requested"] github_action_config.pr_actions: '["opened", "reopened", "ready_for_review", "review_requested"]'
``` ```
`github_action_config.auto_review`, `github_action_config.auto_describe` and `github_action_config.auto_improve` are used to enable/disable automatic tools that run when a new PR is opened. `github_action_config.auto_review`, `github_action_config.auto_describe` and `github_action_config.auto_improve` are used to enable/disable automatic tools that run when a new PR is opened.
If not set, the default configuration is for all three tools to run automatically when a new PR is opened. If not set, the default configuration is for all three tools to run automatically when a new PR is opened.
@ -136,19 +173,22 @@ The JSON structure is equivalent to the yaml data structure defined in [pr_revie
Note that you can give additional config parameters by adding environment variables to `.github/workflows/pr_agent.yml`, or by using a `.pr_agent.toml` [configuration file](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/#global-configuration-file) in the root of your repo Note that you can give additional config parameters by adding environment variables to `.github/workflows/pr_agent.yml`, or by using a `.pr_agent.toml` [configuration file](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/#global-configuration-file) in the root of your repo
For example, you can set an environment variable: `pr_description.publish_labels=false`, or add a `.pr_agent.toml` file with the following content: For example, you can set an environment variable: `pr_description.publish_labels=false`, or add a `.pr_agent.toml` file with the following content:
```
```toml
[pr_description] [pr_description]
publish_labels = false publish_labels = false
``` ```
to prevent Qodo Merge from publishing labels when running the `describe` tool. to prevent Qodo Merge from publishing labels when running the `describe` tool.
## GitLab Webhook ### GitLab Webhook
After setting up a GitLab webhook, to control which commands will run automatically when a new MR is opened, you can set the `pr_commands` parameter in the configuration file, similar to the GitHub App: After setting up a GitLab webhook, to control which commands will run automatically when a new MR is opened, you can set the `pr_commands` parameter in the configuration file, similar to the GitHub App:
```
```toml
[gitlab] [gitlab]
pr_commands = [ pr_commands = [
"/describe", "/describe",
"/review --pr_reviewer.num_code_suggestions=0", "/review",
"/improve", "/improve",
] ]
``` ```
@ -156,24 +196,24 @@ pr_commands = [
the GitLab webhook can also respond to new code that is pushed to an open MR. 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. The configuration parameter `push_commands` defines the list of tools that will be **run automatically** when new code is pushed to the MR.
``` ```toml
[gitlab] [gitlab]
handle_push_trigger = true handle_push_trigger = true
push_commands = [ push_commands = [
"/describe", "/describe",
"/review --pr_reviewer.num_code_suggestions=0 --pr_reviewer.final_update_message=false", "/review",
] ]
``` ```
Note that to use the 'handle_push_trigger' feature, you need to give the gitlab webhook also the "Push events" scope. Note that to use the 'handle_push_trigger' feature, you need to give the gitlab webhook also the "Push events" scope.
## BitBucket App ### BitBucket App
Similar to GitHub app, when running Qodo Merge from BitBucket App, the default [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml) from a pre-built docker will be initially loaded. Similar to GitHub app, when running Qodo Merge from BitBucket App, the default [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml) from a pre-built docker will be initially loaded.
By uploading a local `.pr_agent.toml` file to the root of the repo's main branch, you can edit and customize any configuration parameter. Note that you need to upload `.pr_agent.toml` prior to creating a PR, in order for the configuration to take effect. By uploading a local `.pr_agent.toml` file to the root of the repo's main branch, you can edit and customize any configuration parameter. Note that you need to upload `.pr_agent.toml` prior to creating a PR, in order for the configuration to take effect.
For example, if your local `.pr_agent.toml` file contains: For example, if your local `.pr_agent.toml` file contains:
``` ```toml
[pr_reviewer] [pr_reviewer]
extra_instructions = "Answer in japanese" extra_instructions = "Answer in japanese"
``` ```
@ -182,29 +222,39 @@ Each time you invoke a `/review` tool, it will use the extra instructions you se
Note that among other limitations, BitBucket provides relatively low rate-limits for applications (up to 1000 requests per hour), and does not provide an API to track the actual rate-limit usage. Note that among other limitations, BitBucket provides relatively low rate-limits for applications (up to 1000 requests per hour), and does not provide an API to track the actual rate-limit usage.
If you experience lack of responses from Qodo Merge, you might want to set: `bitbucket_app.avoid_full_files=true` in your configuration file. If you experience a lack of responses from Qodo Merge, you might want to set: `bitbucket_app.avoid_full_files=true` in your configuration file.
This will prevent Qodo Merge from acquiring the full file content, and will only use the diff content. This will reduce the number of requests made to BitBucket, at the cost of small decrease in accuracy, as dynamic context will not be applicable. This will prevent Qodo Merge from acquiring the full file content, and will only use the diff content. This will reduce the number of requests made to BitBucket, at the cost of small decrease in accuracy, as dynamic context will not be applicable.
### BitBucket Self-Hosted App automatic tools #### BitBucket Self-Hosted App automatic tools
To control which commands will run automatically when a new PR is opened, you can set the `pr_commands` parameter in the configuration file: To control which commands will run automatically when a new PR is opened, you can set the `pr_commands` parameter in the configuration file:
Specifically, set the following values: Specifically, set the following values:
``` ```toml
[bitbucket_app] [bitbucket_app]
pr_commands = [ pr_commands = [
"/review --pr_reviewer.num_code_suggestions=0", "/review",
"/improve --pr_code_suggestions.commitable_code_suggestions=true --pr_code_suggestions.suggestions_score_threshold=7", "/improve --pr_code_suggestions.commitable_code_suggestions=true --pr_code_suggestions.suggestions_score_threshold=7",
] ]
``` ```
Note that we set specifically for bitbucket, we recommend using: `--pr_code_suggestions.suggestions_score_threshold=7` and that is the default value we set for bitbucket. Note that we set specifically for bitbucket, we recommend using: `--pr_code_suggestions.suggestions_score_threshold=7` and that is the default value we set for bitbucket.
Since this platform only supports inline code suggestions, we want to limit the number of suggestions, and only present a limited number. Since this platform only supports inline code suggestions, we want to limit the number of suggestions, and only present a limited number.
## Azure DevOps provider To enable BitBucket app to respond to each **push** to the PR, set (for example):
```toml
[bitbucket_app]
handle_push_trigger = true
push_commands = [
"/describe",
"/review",
]
```
### Azure DevOps provider
To use Azure DevOps provider use the following settings in configuration.toml: To use Azure DevOps provider use the following settings in configuration.toml:
``` ```toml
[config] [config]
git_provider="azure" git_provider="azure"
``` ```
@ -223,14 +273,14 @@ org = "https://dev.azure.com/YOUR_ORGANIZATION/"
# pat = "YOUR_PAT_TOKEN" needed only if using PAT for authentication # pat = "YOUR_PAT_TOKEN" needed only if using PAT for authentication
``` ```
### Azure DevOps Webhook #### Azure DevOps Webhook
To control which commands will run automatically when a new PR is opened, you can set the `pr_commands` parameter in the configuration file, similar to the GitHub App: To control which commands will run automatically when a new PR is opened, you can set the `pr_commands` parameter in the configuration file, similar to the GitHub App:
``` ```toml
[azure_devops_server] [azure_devops_server]
pr_commands = [ pr_commands = [
"/describe", "/describe",
"/review --pr_reviewer.num_code_suggestions=0", "/review",
"/improve", "/improve",
] ]
``` ```

View File

@ -1,11 +1,10 @@
## Changing a model ## Changing a model in PR-Agent
See [here](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/algo/__init__.py) for a list of available models. See [here](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/algo/__init__.py) for a list of available models.
To use a different model than the default (GPT-4), you need to edit in the [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L2) the fields: To use a different model than the default (GPT-4), you need to edit in the [configuration file](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/settings/configuration.toml#L2) the fields:
``` ```
[config] [config]
model = "..." model = "..."
model_turbo = "..."
fallback_models = ["..."] fallback_models = ["..."]
``` ```
@ -27,57 +26,51 @@ deployment_id = "" # The deployment name you chose when you deployed the engine
and set in your configuration file: and set in your configuration file:
``` ```
[config] [config]
model="" # the OpenAI model you've deployed on Azure (e.g. gpt-3.5-turbo) model="" # the OpenAI model you've deployed on Azure (e.g. gpt-4o)
model_turbo="" # the OpenAI model you've deployed on Azure (e.g. gpt-3.5-turbo) fallback_models=["..."]
fallback_models=["..."] # the OpenAI model you've deployed on Azure (e.g. gpt-3.5-turbo)
``` ```
Passing custom headers to the underlying LLM Model API can be done by setting extra_headers parameter to litellm.
```
[litellm]
extra_headers='{"projectId": "<authorized projectId >", ...}') #The value of this setting should be a JSON string representing the desired headers, a ValueError is thrown otherwise.
```
This enables users to pass authorization tokens or API keys, when routing requests through an API management gateway.
### Ollama
You can run models locally through either [VLLM](https://docs.litellm.ai/docs/providers/vllm) or [Ollama](https://docs.litellm.ai/docs/providers/ollama)
E.g. to use a new model locally via Ollama, set in `.secrets.toml` or in a configuration file:
```
[config]
model = "ollama/qwen2.5-coder:32b"
fallback_models=["ollama/qwen2.5-coder:32b"]
custom_model_max_tokens=128000 # set the maximal input tokens for the model
duplicate_examples=true # will duplicate the examples in the prompt, to help the model to generate structured output
[ollama]
api_base = "http://localhost:11434" # or whatever port you're running Ollama on
```
!!! note "Local models vs commercial models"
Qodo Merge is compatible with almost any AI model, but analyzing complex code repositories and pull requests requires a model specifically optimized for code analysis.
Commercial models such as GPT-4, Claude Sonnet, and Gemini have demonstrated robust capabilities in generating structured output for code analysis tasks with large input. In contrast, most open-source models currently available (as of January 2025) face challenges with these complex tasks.
Based on our testing, local open-source models are suitable for experimentation and learning purposes (mainly for the `ask` command), but they are not suitable for production-level code analysis tasks.
Hence, for production workflows and real-world usage, we recommend using commercial models.
### Hugging Face ### Hugging Face
**Local**
You can run Hugging Face models locally through either [VLLM](https://docs.litellm.ai/docs/providers/vllm) or [Ollama](https://docs.litellm.ai/docs/providers/ollama)
E.g. to use a new Hugging Face model locally via Ollama, set:
```
[__init__.py]
MAX_TOKENS = {
"model-name-on-ollama": <max_tokens>
}
e.g.
MAX_TOKENS={
...,
"ollama/llama2": 4096
}
[config] # in configuration.toml
model = "ollama/llama2"
model_turbo = "ollama/llama2"
fallback_models=["ollama/llama2"]
[ollama] # in .secrets.toml
api_base = ... # the base url for your Hugging Face inference endpoint
# e.g. if running Ollama locally, you may use:
api_base = "http://localhost:11434/"
```
### Inference Endpoints
To use a new model with Hugging Face Inference Endpoints, for example, set: To use a new model with Hugging Face Inference Endpoints, for example, set:
``` ```
[__init__.py]
MAX_TOKENS = {
"model-name-on-huggingface": <max_tokens>
}
e.g.
MAX_TOKENS={
...,
"meta-llama/Llama-2-7b-chat-hf": 4096
}
[config] # in configuration.toml [config] # in configuration.toml
model = "huggingface/meta-llama/Llama-2-7b-chat-hf" model = "huggingface/meta-llama/Llama-2-7b-chat-hf"
model_turbo = "huggingface/meta-llama/Llama-2-7b-chat-hf"
fallback_models=["huggingface/meta-llama/Llama-2-7b-chat-hf"] fallback_models=["huggingface/meta-llama/Llama-2-7b-chat-hf"]
custom_model_max_tokens=... # set the maximal input tokens for the model
[huggingface] # in .secrets.toml [huggingface] # in .secrets.toml
key = ... # your Hugging Face api key key = ... # your Hugging Face api key
@ -91,7 +84,6 @@ To use Llama2 model with Replicate, for example, set:
``` ```
[config] # in configuration.toml [config] # in configuration.toml
model = "replicate/llama-2-70b-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1" model = "replicate/llama-2-70b-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1"
model_turbo = "replicate/llama-2-70b-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1"
fallback_models=["replicate/llama-2-70b-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1"] fallback_models=["replicate/llama-2-70b-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1"]
[replicate] # in .secrets.toml [replicate] # in .secrets.toml
key = ... key = ...
@ -107,7 +99,6 @@ To use Llama3 model with Groq, for example, set:
``` ```
[config] # in configuration.toml [config] # in configuration.toml
model = "llama3-70b-8192" 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 [groq] # in .secrets.toml
key = ... # your Groq api key key = ... # your Groq api key
@ -121,7 +112,6 @@ To use Google's Vertex AI platform and its associated models (chat-bison/codecha
``` ```
[config] # in configuration.toml [config] # in configuration.toml
model = "vertex_ai/codechat-bison" model = "vertex_ai/codechat-bison"
model_turbo = "vertex_ai/codechat-bison"
fallback_models="vertex_ai/codechat-bison" fallback_models="vertex_ai/codechat-bison"
[vertexai] # in .secrets.toml [vertexai] # in .secrets.toml
@ -140,7 +130,6 @@ To use [Google AI Studio](https://aistudio.google.com/) models, set the relevant
```toml ```toml
[config] # in configuration.toml [config] # in configuration.toml
model="google_ai_studio/gemini-1.5-flash" model="google_ai_studio/gemini-1.5-flash"
model_turbo="google_ai_studio/gemini-1.5-flash"
fallback_models=["google_ai_studio/gemini-1.5-flash"] fallback_models=["google_ai_studio/gemini-1.5-flash"]
[google_ai_studio] # in .secrets.toml [google_ai_studio] # in .secrets.toml
@ -156,7 +145,6 @@ To use Anthropic models, set the relevant models in the configuration section of
``` ```
[config] [config]
model="anthropic/claude-3-opus-20240229" model="anthropic/claude-3-opus-20240229"
model_turbo="anthropic/claude-3-opus-20240229"
fallback_models=["anthropic/claude-3-opus-20240229"] fallback_models=["anthropic/claude-3-opus-20240229"]
``` ```
@ -173,7 +161,6 @@ To use Amazon Bedrock and its foundational models, add the below configuration:
``` ```
[config] # in configuration.toml [config] # in configuration.toml
model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0" model="bedrock/anthropic.claude-3-sonnet-20240229-v1:0"
model_turbo="bedrock/anthropic.claude-3-sonnet-20240229-v1:0"
fallback_models=["bedrock/anthropic.claude-v2:1"] fallback_models=["bedrock/anthropic.claude-v2:1"]
``` ```
@ -187,20 +174,50 @@ drop_params = true
AWS session is automatically authenticated from your environment, but you can also explicitly set `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_REGION_NAME` environment variables. Please refer to [this document](https://litellm.vercel.app/docs/providers/bedrock) for more details. AWS session is automatically authenticated from your environment, but you can also explicitly set `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_REGION_NAME` environment variables. Please refer to [this document](https://litellm.vercel.app/docs/providers/bedrock) for more details.
### DeepSeek
To use deepseek-chat model with DeepSeek, for example, set:
```toml
[config] # in configuration.toml
model = "deepseek/deepseek-chat"
fallback_models=["deepseek/deepseek-chat"]
```
and fill up your key
```toml
[deepseek] # in .secrets.toml
key = ...
```
(you can obtain a deepseek-chat key from [here](https://platform.deepseek.com))
### Custom models ### Custom models
If the relevant model doesn't appear [here](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/algo/__init__.py), you can still use it as a custom model: If the relevant model doesn't appear [here](https://github.com/Codium-ai/pr-agent/blob/main/pr_agent/algo/__init__.py), you can still use it as a custom model:
(1) Set the model name in the configuration file: 1. Set the model name in the configuration file:
``` ```
[config] [config]
model="custom_model_name" model="custom_model_name"
model_turbo="custom_model_name"
fallback_models=["custom_model_name"] fallback_models=["custom_model_name"]
``` ```
(2) Set the maximal tokens for the model: 2. Set the maximal tokens for the model:
``` ```
[config] [config]
custom_model_max_tokens= ... custom_model_max_tokens= ...
``` ```
(3) Go to [litellm documentation](https://litellm.vercel.app/docs/proxy/quick_start#supported-llms), find the model you want to use, and set the relevant environment variables. 3. Go to [litellm documentation](https://litellm.vercel.app/docs/proxy/quick_start#supported-llms), find the model you want to use, and set the relevant environment variables.
4. Most reasoning models do not support chat-style inputs (`system` and `user` messages) or temperature settings.
To bypass chat templates and temperature controls, set `config.custom_reasoning_model = true` in your configuration file.
## Dedicated parameters
### OpenAI models
[config]
reasoning_efffort= = "medium" # "low", "medium", "high"
With the OpenAI models that support reasoning effort (eg: o3-mini), you can specify its reasoning effort via `config` section. The default value is `medium`. You can change it to `high` or `low` based on your usage.

View File

@ -20,7 +20,7 @@ In terms of precedence, wiki configurations will override local configurations,
`Platforms supported: GitHub, GitLab, Bitbucket` `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, 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**. 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**.

View File

@ -0,0 +1,33 @@
`Supported Git Platforms: GitHub, GitLab, Bitbucket`
For optimal functionality of Qodo Merge, we recommend enabling a wiki for each repository where Qodo Merge is installed. The wiki serves several important purposes:
**Key Wiki Features: 💎**
- Storing a [configuration file](https://qodo-merge-docs.qodo.ai/usage-guide/configuration_options/#wiki-configuration-file)
- Defining a [`best_practices.md`](https://qodo-merge-docs.qodo.ai/tools/improve/#best-practices) file
- Track [accepted suggestions](https://qodo-merge-docs.qodo.ai/tools/improve/#suggestion-tracking)
- Facilitates learning over time by creating an [auto_best_practices.md](https://qodo-merge-docs.qodo.ai/core-abilities/auto_best_practices) file
**Setup Instructions (GitHub):**
To enable a wiki for your repository:
1. Navigate to your repository's main page on GitHub
2. Select "Settings" from the top navigation bar
3. Locate the "Features" section
4. Enable the "Wikis" option by checking the corresponding box
5. Return to your repository's main page
6. Look for the newly added "Wiki" tab in the top navigation
7. Initialize your wiki by clicking "Create the first page" and saving (this step is important - without creating an initial page, the wiki will not be fully functional)
### Why Wiki?
- Your code (and its derivatives, including accepted code suggestions) is yours. Qodo Merge will never store it on external servers.
- Repository changes typically require pull requests, which create overhead and are time-consuming. This process is too cumbersome for auto data aggregation, and is not very convenient even for managing frequently updated content like configuration files and best practices.
- A repository wiki page provides an ideal balance:
- It lives within your repository, making it suitable for code-related documentation
- It enables quick updates without the overhead of pull requests
- It maintains full Git version control, allowing you to track changes over time.

View File

@ -5,6 +5,7 @@ It includes information on how to adjust Qodo Merge configurations, define which
- [Introduction](./introduction.md) - [Introduction](./introduction.md)
- [Enabling a Wiki](./enabling_a_wiki)
- [Configuration File](./configuration_options.md) - [Configuration File](./configuration_options.md)
- [Usage and Automation](./automations_and_usage.md) - [Usage and Automation](./automations_and_usage.md)
- [Local Repo (CLI)](./automations_and_usage.md#local-repo-cli) - [Local Repo (CLI)](./automations_and_usage.md#local-repo-cli)
@ -23,4 +24,4 @@ It includes information on how to adjust Qodo Merge configurations, define which
- [Changing a model](./additional_configurations.md#changing-a-model) - [Changing a model](./additional_configurations.md#changing-a-model)
- [Patch Extra Lines](./additional_configurations.md#patch-extra-lines) - [Patch Extra Lines](./additional_configurations.md#patch-extra-lines)
- [Editing the prompts](./additional_configurations.md#editing-the-prompts) - [Editing the prompts](./additional_configurations.md#editing-the-prompts)
- [Qodo Merge Pro Models](./PR_agent_pro_models.md) - [Qodo Merge Models](./qodo_merge_models)

View File

@ -2,7 +2,7 @@
After [installation](https://qodo-merge-docs.qodo.ai/installation/), there are three basic ways to invoke Qodo Merge: After [installation](https://qodo-merge-docs.qodo.ai/installation/), there are three basic ways to invoke Qodo Merge:
1. Locally running a CLI command 1. Locally running a CLI command
2. Online usage - by [commenting](https://github.com/Codium-ai/pr-agent/pull/229#issuecomment-1695021901) on a PR 2. Online usage - by [commenting](https://github.com/Codium-ai/pr-agent/pull/229#issuecomment-1695021901){:target="_blank"} on a PR
3. Enabling Qodo Merge tools to run automatically when a new PR is opened 3. Enabling Qodo Merge tools to run automatically when a new PR is opened
@ -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). 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. These platforms also enable to run Qodo Merge specific tools automatically when a new PR is opened, or on each push to a branch.

View File

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

View File

@ -1,29 +1,26 @@
site_name: Qodo Merge (formerly known as PR-Agent) site_name: Qodo Merge (and open-source PR-Agent)
repo_url: https://github.com/Codium-ai/pr-agent repo_url: https://github.com/qodo-ai/pr-agent
repo_name: Codium-ai/pr-agent repo_name: Qodo-ai/pr-agent
nav: nav:
- Overview: - Overview:
- 'index.md' - 'index.md'
- 💎 Qodo Merge Pro: 'overview/pr_agent_pro.md' - 💎 Qodo Merge: 'overview/pr_agent_pro.md'
- Data Privacy: 'overview/data_privacy.md' - Data Privacy: 'overview/data_privacy.md'
- Installation: - Installation:
- 'installation/index.md' - 'installation/index.md'
- Locally: 'installation/locally.md' - PR-Agent: 'installation/pr_agent.md'
- GitHub: 'installation/github.md' - 💎 Qodo Merge: 'installation/qodo_merge.md'
- GitLab: 'installation/gitlab.md'
- BitBucket: 'installation/bitbucket.md'
- Azure DevOps: 'installation/azure.md'
- 💎 Qodo Merge Pro: 'installation/pr_agent_pro.md'
- Usage Guide: - Usage Guide:
- 'usage-guide/index.md' - 'usage-guide/index.md'
- Introduction: 'usage-guide/introduction.md' - Introduction: 'usage-guide/introduction.md'
- Enabling a Wiki: 'usage-guide/enabling_a_wiki.md'
- Configuration File: 'usage-guide/configuration_options.md' - Configuration File: 'usage-guide/configuration_options.md'
- Usage and Automation: 'usage-guide/automations_and_usage.md' - Usage and Automation: 'usage-guide/automations_and_usage.md'
- Managing Mail Notifications: 'usage-guide/mail_notifications.md' - Managing Mail Notifications: 'usage-guide/mail_notifications.md'
- Changing a Model: 'usage-guide/changing_a_model.md' - Changing a Model: 'usage-guide/changing_a_model.md'
- Additional Configurations: 'usage-guide/additional_configurations.md' - Additional Configurations: 'usage-guide/additional_configurations.md'
- 💎 Qodo Merge Pro Models: 'usage-guide/PR_agent_pro_models' - 💎 Qodo Merge Models: 'usage-guide/qodo_merge_models.md'
- Tools: - Tools:
- 'tools/index.md' - 'tools/index.md'
- Describe: 'tools/describe.md' - Describe: 'tools/describe.md'
@ -41,8 +38,11 @@ nav:
- 💎 Custom Prompt: 'tools/custom_prompt.md' - 💎 Custom Prompt: 'tools/custom_prompt.md'
- 💎 CI Feedback: 'tools/ci_feedback.md' - 💎 CI Feedback: 'tools/ci_feedback.md'
- 💎 Similar Code: 'tools/similar_code.md' - 💎 Similar Code: 'tools/similar_code.md'
- 💎 Implement: 'tools/implement.md'
- Core Abilities: - Core Abilities:
- 'core-abilities/index.md' - 'core-abilities/index.md'
- Fetching ticket context: 'core-abilities/fetching_ticket_context.md'
- Auto best practices: 'core-abilities/auto_best_practices.md'
- Local and global metadata: 'core-abilities/metadata.md' - Local and global metadata: 'core-abilities/metadata.md'
- Dynamic context: 'core-abilities/dynamic_context.md' - Dynamic context: 'core-abilities/dynamic_context.md'
- Self-reflection: 'core-abilities/self_reflection.md' - Self-reflection: 'core-abilities/self_reflection.md'
@ -58,6 +58,7 @@ nav:
- Data Privacy: 'chrome-extension/data_privacy.md' - Data Privacy: 'chrome-extension/data_privacy.md'
- FAQ: - FAQ:
- FAQ: 'faq/index.md' - FAQ: 'faq/index.md'
- AI Docs Search: 'ai_search/index.md'
# - Code Fine-tuning Benchmark: 'finetuning_benchmark/index.md' # - Code Fine-tuning Benchmark: 'finetuning_benchmark/index.md'
theme: theme:
@ -153,4 +154,4 @@ markdown_extensions:
copyright: | copyright: |
&copy; 2024 <a href="https://www.codium.ai/" target="_blank" rel="noopener">CodiumAI</a> &copy; 2025 <a href="https://www.codium.ai/" target="_blank" rel="noopener">QodoAI</a>

View File

@ -82,7 +82,7 @@
<footer class="wrapper"> <footer class="wrapper">
<div class="container"> <div class="container">
<p class="footer-text">© 2024 <a href="https://www.qodo.ai/" target="_blank" rel="noopener">Qodo</a></p> <p class="footer-text">© 2025 <a href="https://www.qodo.ai/" target="_blank" rel="noopener">Qodo</a></p>
<div class="footer-links"> <div class="footer-links">
<a href="https://qodo-gen-docs.qodo.ai/">Qodo Gen</a> <a href="https://qodo-gen-docs.qodo.ai/">Qodo Gen</a>
<p>|</p> <p>|</p>

View File

@ -3,5 +3,5 @@
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 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); 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-5C9KZBM3');</script> })(window,document,'script','dataLayer','GTM-M6PJSFV');</script>
<!-- End Google Tag Manager --> <!-- End Google Tag Manager -->

View File

@ -1 +0,0 @@

View File

@ -3,7 +3,7 @@ from functools import partial
from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler
from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler from pr_agent.algo.ai_handlers.litellm_ai_handler import LiteLLMAIHandler
from pr_agent.algo.cli_args import CliArgs
from pr_agent.algo.utils import update_settings_from_args from pr_agent.algo.utils import update_settings_from_args
from pr_agent.config_loader import get_settings from pr_agent.config_loader import get_settings
from pr_agent.git_providers.utils import apply_repo_settings from pr_agent.git_providers.utils import apply_repo_settings
@ -14,7 +14,6 @@ from pr_agent.tools.pr_config import PRConfig
from pr_agent.tools.pr_description import PRDescription from pr_agent.tools.pr_description import PRDescription
from pr_agent.tools.pr_generate_labels import PRGenerateLabels from pr_agent.tools.pr_generate_labels import PRGenerateLabels
from pr_agent.tools.pr_help_message import PRHelpMessage from pr_agent.tools.pr_help_message import PRHelpMessage
from pr_agent.tools.pr_information_from_user import PRInformationFromUser
from pr_agent.tools.pr_line_questions import PR_LineQuestions from pr_agent.tools.pr_line_questions import PR_LineQuestions
from pr_agent.tools.pr_questions import PRQuestions from pr_agent.tools.pr_questions import PRQuestions
from pr_agent.tools.pr_reviewer import PRReviewer from pr_agent.tools.pr_reviewer import PRReviewer
@ -26,8 +25,6 @@ command2class = {
"answer": PRReviewer, "answer": PRReviewer,
"review": PRReviewer, "review": PRReviewer,
"review_pr": PRReviewer, "review_pr": PRReviewer,
"reflect": PRInformationFromUser,
"reflect_and_review": PRInformationFromUser,
"describe": PRDescription, "describe": PRDescription,
"describe_pr": PRDescription, "describe_pr": PRDescription,
"improve": PRCodeSuggestions, "improve": PRCodeSuggestions,
@ -47,10 +44,10 @@ command2class = {
commands = list(command2class.keys()) commands = list(command2class.keys())
class PRAgent: class PRAgent:
def __init__(self, ai_handler: partial[BaseAiHandler,] = LiteLLMAIHandler): def __init__(self, ai_handler: partial[BaseAiHandler,] = LiteLLMAIHandler):
self.ai_handler = ai_handler # will be initialized in run_action self.ai_handler = ai_handler # will be initialized in run_action
self.forbidden_cli_args = ['enable_auto_approval']
async def handle_request(self, pr_url, request, notify=None) -> bool: async def handle_request(self, pr_url, request, notify=None) -> bool:
# First, apply repo specific settings if exists # First, apply repo specific settings if exists
@ -65,24 +62,37 @@ class PRAgent:
else: else:
action, *args = request action, *args = request
if args: # validate args
for forbidden_arg in self.forbidden_cli_args: is_valid, arg = CliArgs.validate_user_args(args)
for arg in args: if not is_valid:
if forbidden_arg in arg:
get_logger().error( get_logger().error(
f"CLI argument for param '{forbidden_arg}' is forbidden. Use instead a configuration file." f"CLI argument for param '{arg}' is forbidden. Use instead a configuration file."
) )
return False return False
# Update settings from args
args = update_settings_from_args(args) args = update_settings_from_args(args)
# Append the response language in the extra instructions
response_language = get_settings().config.get('response_language', 'en-us')
if response_language.lower() != 'en-us':
get_logger().info(f'User has set the response language to: {response_language}')
for key in get_settings():
setting = get_settings().get(key)
if str(type(setting)) == "<class 'dynaconf.utils.boxing.DynaBox'>":
if hasattr(setting, 'extra_instructions'):
current_extra_instructions = setting.extra_instructions
if current_extra_instructions:
setting.extra_instructions = current_extra_instructions+ f"\n======\n\nIn addition, Your response MUST be written in the language corresponding to local code: {response_language}. This is crucial."
else:
setting.extra_instructions = f"Your response MUST be written in the language corresponding to locale code: '{response_language}'. This is crucial."
action = action.lstrip("/").lower() action = action.lstrip("/").lower()
if action not in command2class: if action not in command2class:
get_logger().debug(f"Unknown command: {action}") get_logger().error(f"Unknown command: {action}")
return False return False
with get_logger().contextualize(command=action, pr_url=pr_url): with get_logger().contextualize(command=action, pr_url=pr_url):
get_logger().info("PR-Agent request handler started", analytics=True) get_logger().info("PR-Agent request handler started", analytics=True)
if action == "reflect_and_review":
get_settings().pr_reviewer.ask_and_reflect = True
if action == "answer": if action == "answer":
if notify: if notify:
notify() notify()

View File

@ -19,27 +19,38 @@ MAX_TOKENS = {
'gpt-4o-mini': 128000, # 128K, but may be limited by config.max_model_tokens 'gpt-4o-mini': 128000, # 128K, but may be limited by config.max_model_tokens
'gpt-4o-mini-2024-07-18': 128000, # 128K, but may be limited by config.max_model_tokens 'gpt-4o-mini-2024-07-18': 128000, # 128K, but may be limited by config.max_model_tokens
'gpt-4o-2024-08-06': 128000, # 128K, but may be limited by config.max_model_tokens 'gpt-4o-2024-08-06': 128000, # 128K, but may be limited by config.max_model_tokens
'gpt-4o-2024-11-20': 128000, # 128K, but may be limited by config.max_model_tokens
'o1-mini': 128000, # 128K, but may be limited by config.max_model_tokens 'o1-mini': 128000, # 128K, but may be limited by config.max_model_tokens
'o1-mini-2024-09-12': 128000, # 128K, but may be limited by config.max_model_tokens 'o1-mini-2024-09-12': 128000, # 128K, but may be limited by config.max_model_tokens
'o1-preview': 128000, # 128K, but may be limited by config.max_model_tokens 'o1-preview': 128000, # 128K, but may be limited by config.max_model_tokens
'o1-preview-2024-09-12': 128000, # 128K, but may be limited by config.max_model_tokens 'o1-preview-2024-09-12': 128000, # 128K, but may be limited by config.max_model_tokens
'o1-2024-12-17': 204800, # 200K, but may be limited by config.max_model_tokens
'o1': 204800, # 200K, but may be limited by config.max_model_tokens
'o3-mini': 204800, # 200K, but may be limited by config.max_model_tokens
'o3-mini-2025-01-31': 204800, # 200K, but may be limited by config.max_model_tokens
'claude-instant-1': 100000, 'claude-instant-1': 100000,
'claude-2': 100000, 'claude-2': 100000,
'command-nightly': 4096, 'command-nightly': 4096,
'deepseek/deepseek-chat': 128000, # 128K, but may be limited by config.max_model_tokens
'deepseek/deepseek-reasoner': 64000, # 64K, but may be limited by config.max_model_tokens
'replicate/llama-2-70b-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1': 4096, 'replicate/llama-2-70b-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1': 4096,
'meta-llama/Llama-2-7b-chat-hf': 4096, 'meta-llama/Llama-2-7b-chat-hf': 4096,
'vertex_ai/codechat-bison': 6144, 'vertex_ai/codechat-bison': 6144,
'vertex_ai/codechat-bison-32k': 32000, 'vertex_ai/codechat-bison-32k': 32000,
'vertex_ai/claude-3-haiku@20240307': 100000, 'vertex_ai/claude-3-haiku@20240307': 100000,
'vertex_ai/claude-3-5-haiku@20241022': 100000,
'vertex_ai/claude-3-sonnet@20240229': 100000, 'vertex_ai/claude-3-sonnet@20240229': 100000,
'vertex_ai/claude-3-opus@20240229': 100000, 'vertex_ai/claude-3-opus@20240229': 100000,
'vertex_ai/claude-3-5-sonnet@20240620': 100000, 'vertex_ai/claude-3-5-sonnet@20240620': 100000,
'vertex_ai/claude-3-5-sonnet-v2@20241022': 100000, 'vertex_ai/claude-3-5-sonnet-v2@20241022': 100000,
'vertex_ai/claude-3-7-sonnet@20250219': 200000,
'vertex_ai/gemini-1.5-pro': 1048576, 'vertex_ai/gemini-1.5-pro': 1048576,
'vertex_ai/gemini-1.5-flash': 1048576, 'vertex_ai/gemini-1.5-flash': 1048576,
'vertex_ai/gemini-2.0-flash': 1048576,
'vertex_ai/gemma2': 8200, 'vertex_ai/gemma2': 8200,
'gemini/gemini-1.5-pro': 1048576, 'gemini/gemini-1.5-pro': 1048576,
'gemini/gemini-1.5-flash': 1048576, 'gemini/gemini-1.5-flash': 1048576,
'gemini/gemini-2.0-flash': 1048576,
'codechat-bison': 6144, 'codechat-bison': 6144,
'codechat-bison-32k': 32000, 'codechat-bison-32k': 32000,
'anthropic.claude-instant-v1': 100000, 'anthropic.claude-instant-v1': 100000,
@ -48,20 +59,25 @@ MAX_TOKENS = {
'anthropic/claude-3-opus-20240229': 100000, 'anthropic/claude-3-opus-20240229': 100000,
'anthropic/claude-3-5-sonnet-20240620': 100000, 'anthropic/claude-3-5-sonnet-20240620': 100000,
'anthropic/claude-3-5-sonnet-20241022': 100000, 'anthropic/claude-3-5-sonnet-20241022': 100000,
'anthropic/claude-3-7-sonnet-20250219': 200000,
'anthropic/claude-3-5-haiku-20241022': 100000,
'bedrock/anthropic.claude-instant-v1': 100000, 'bedrock/anthropic.claude-instant-v1': 100000,
'bedrock/anthropic.claude-v2': 100000, 'bedrock/anthropic.claude-v2': 100000,
'bedrock/anthropic.claude-v2:1': 100000, 'bedrock/anthropic.claude-v2:1': 100000,
'bedrock/anthropic.claude-3-sonnet-20240229-v1:0': 100000, 'bedrock/anthropic.claude-3-sonnet-20240229-v1:0': 100000,
'bedrock/anthropic.claude-3-haiku-20240307-v1:0': 100000, 'bedrock/anthropic.claude-3-haiku-20240307-v1:0': 100000,
'bedrock/anthropic.claude-3-5-haiku-20241022-v1:0': 100000,
'bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0': 100000, 'bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0': 100000,
'bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0': 100000, 'bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0': 100000,
'bedrock/anthropic.claude-3-7-sonnet-20250219-v1:0': 200000,
"bedrock/us.anthropic.claude-3-5-sonnet-20241022-v2:0": 100000,
'claude-3-5-sonnet': 100000, 'claude-3-5-sonnet': 100000,
'groq/llama3-8b-8192': 8192, 'groq/llama3-8b-8192': 8192,
'groq/llama3-70b-8192': 8192, 'groq/llama3-70b-8192': 8192,
'groq/llama-3.1-8b-instant': 8192,
'groq/llama-3.3-70b-versatile': 128000,
'groq/mixtral-8x7b-32768': 32768, 'groq/mixtral-8x7b-32768': 32768,
'groq/llama-3.1-8b-instant': 131072, 'groq/gemma2-9b-it': 8192,
'groq/llama-3.1-70b-versatile': 131072,
'groq/llama-3.1-405b-reasoning': 131072,
'ollama/llama3': 4096, 'ollama/llama3': 4096,
'watsonx/meta-llama/llama-3-8b-instruct': 4096, 'watsonx/meta-llama/llama-3-8b-instruct': 4096,
"watsonx/meta-llama/llama-3-70b-instruct": 4096, "watsonx/meta-llama/llama-3-70b-instruct": 4096,
@ -70,3 +86,26 @@ MAX_TOKENS = {
"watsonx/ibm/granite-34b-code-instruct": 8191, "watsonx/ibm/granite-34b-code-instruct": 8191,
"watsonx/mistralai/mistral-large": 32768, "watsonx/mistralai/mistral-large": 32768,
} }
USER_MESSAGE_ONLY_MODELS = [
"deepseek/deepseek-reasoner",
"o1-mini",
"o1-mini-2024-09-12",
"o1-preview"
]
NO_SUPPORT_TEMPERATURE_MODELS = [
"deepseek/deepseek-reasoner",
"o1-mini",
"o1-mini-2024-09-12",
"o1",
"o1-2024-12-17",
"o3-mini",
"o3-mini-2025-01-31",
"o1-preview"
]
SUPPORT_REASONING_EFFORT_MODELS = [
"o3-mini",
"o3-mini-2025-01-31"
]

View File

@ -1,17 +1,18 @@
try: try:
from langchain_openai import ChatOpenAI, AzureChatOpenAI from langchain_core.messages import HumanMessage, SystemMessage
from langchain_core.messages import SystemMessage, HumanMessage from langchain_openai import AzureChatOpenAI, ChatOpenAI
except: # we don't enforce langchain as a dependency, so if it's not installed, just move on except: # we don't enforce langchain as a dependency, so if it's not installed, just move on
pass pass
import functools
from openai import APIError, RateLimitError, Timeout
from retry import retry
from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler
from pr_agent.config_loader import get_settings from pr_agent.config_loader import get_settings
from pr_agent.log import get_logger from pr_agent.log import get_logger
from openai import APIError, RateLimitError, Timeout
from retry import retry
import functools
OPENAI_RETRIES = 5 OPENAI_RETRIES = 5
@ -73,4 +74,3 @@ class LangChainOpenAIHandler(BaseAiHandler):
raise ValueError(f"OpenAI {e.name} is required") from e raise ValueError(f"OpenAI {e.name} is required") from e
else: else:
raise e raise e

View File

@ -1,13 +1,17 @@
import os import os
import requests
import litellm import litellm
import openai import openai
import requests
from litellm import acompletion from litellm import acompletion
from tenacity import retry, retry_if_exception_type, stop_after_attempt from tenacity import retry, retry_if_exception_type, stop_after_attempt
from pr_agent.algo import NO_SUPPORT_TEMPERATURE_MODELS, SUPPORT_REASONING_EFFORT_MODELS, USER_MESSAGE_ONLY_MODELS
from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler from pr_agent.algo.ai_handlers.base_ai_handler import BaseAiHandler
from pr_agent.algo.utils import ReasoningEffort, get_version
from pr_agent.config_loader import get_settings from pr_agent.config_loader import get_settings
from pr_agent.log import get_logger from pr_agent.log import get_logger
import json
OPENAI_RETRIES = 5 OPENAI_RETRIES = 5
@ -88,6 +92,19 @@ class LiteLLMAIHandler(BaseAiHandler):
if get_settings().get("GOOGLE_AI_STUDIO.GEMINI_API_KEY", None): if get_settings().get("GOOGLE_AI_STUDIO.GEMINI_API_KEY", None):
os.environ["GEMINI_API_KEY"] = get_settings().google_ai_studio.gemini_api_key os.environ["GEMINI_API_KEY"] = get_settings().google_ai_studio.gemini_api_key
# Support deepseek models
if get_settings().get("DEEPSEEK.KEY", None):
os.environ['DEEPSEEK_API_KEY'] = get_settings().get("DEEPSEEK.KEY")
# Models that only use user meessage
self.user_message_only_models = USER_MESSAGE_ONLY_MODELS
# Model that doesn't support temperature argument
self.no_support_temperature_models = NO_SUPPORT_TEMPERATURE_MODELS
# Models that support reasoning effort
self.support_reasoning_models = SUPPORT_REASONING_EFFORT_MODELS
def prepare_logs(self, response, system, user, resp, finish_reason): def prepare_logs(self, response, system, user, resp, finish_reason):
response_log = response.dict().copy() response_log = response.dict().copy()
response_log['system'] = system response_log['system'] = system
@ -131,7 +148,7 @@ class LiteLLMAIHandler(BaseAiHandler):
if "langfuse" in callbacks: if "langfuse" in callbacks:
metadata.update({ metadata.update({
"trace_name": command, "trace_name": command,
"tags": [git_provider, command], "tags": [git_provider, command, f'version:{get_version()}'],
"trace_metadata": { "trace_metadata": {
"command": command, "command": command,
"pr_url": pr_url, "pr_url": pr_url,
@ -140,7 +157,7 @@ class LiteLLMAIHandler(BaseAiHandler):
if "langsmith" in callbacks: if "langsmith" in callbacks:
metadata.update({ metadata.update({
"run_name": command, "run_name": command,
"tags": [git_provider, command], "tags": [git_provider, command, f'version:{get_version()}'],
"extra": { "extra": {
"metadata": { "metadata": {
"command": command, "command": command,
@ -191,13 +208,11 @@ class LiteLLMAIHandler(BaseAiHandler):
messages[1]["content"] = [{"type": "text", "text": messages[1]["content"]}, messages[1]["content"] = [{"type": "text", "text": messages[1]["content"]},
{"type": "image_url", "image_url": {"url": img_path}}] {"type": "image_url", "image_url": {"url": img_path}}]
# Currently O1 does not support separate system and user prompts # Currently, some models do not support a separate system and user prompts
O1_MODEL_PREFIX = 'o1-' if model in self.user_message_only_models or get_settings().config.custom_reasoning_model:
model_type = model.split('/')[-1] if '/' in model else model
if model_type.startswith(O1_MODEL_PREFIX):
user = f"{system}\n\n\n{user}" user = f"{system}\n\n\n{user}"
system = "" system = ""
get_logger().info(f"Using O1 model, combining system and user prompts") get_logger().info(f"Using model {model}, combining system and user prompts")
messages = [{"role": "user", "content": user}] messages = [{"role": "user", "content": user}]
kwargs = { kwargs = {
"model": model, "model": model,
@ -211,11 +226,22 @@ class LiteLLMAIHandler(BaseAiHandler):
"model": model, "model": model,
"deployment_id": deployment_id, "deployment_id": deployment_id,
"messages": messages, "messages": messages,
"temperature": temperature,
"timeout": get_settings().config.ai_timeout, "timeout": get_settings().config.ai_timeout,
"api_base": self.api_base, "api_base": self.api_base,
} }
# Add temperature only if model supports it
if model not in self.no_support_temperature_models and not get_settings().config.custom_reasoning_model:
# get_logger().info(f"Adding temperature with value {temperature} to model {model}.")
kwargs["temperature"] = temperature
# Add reasoning_effort if model supports it
if (model in self.support_reasoning_models):
supported_reasoning_efforts = [ReasoningEffort.HIGH.value, ReasoningEffort.MEDIUM.value, ReasoningEffort.LOW.value]
reasoning_effort = get_settings().config.reasoning_effort if (get_settings().config.reasoning_effort in supported_reasoning_efforts) else ReasoningEffort.MEDIUM.value
get_logger().info(f"Adding reasoning_effort with value {reasoning_effort} to model {model}.")
kwargs["reasoning_effort"] = reasoning_effort
if get_settings().litellm.get("enable_callbacks", False): if get_settings().litellm.get("enable_callbacks", False):
kwargs = self.add_litellm_callbacks(kwargs) kwargs = self.add_litellm_callbacks(kwargs)
@ -229,6 +255,16 @@ class LiteLLMAIHandler(BaseAiHandler):
if self.repetition_penalty: if self.repetition_penalty:
kwargs["repetition_penalty"] = self.repetition_penalty kwargs["repetition_penalty"] = self.repetition_penalty
#Added support for extra_headers while using litellm to call underlying model, via a api management gateway, would allow for passing custom headers for security and authorization
if get_settings().get("LITELLM.EXTRA_HEADERS", None):
try:
litellm_extra_headers = json.loads(get_settings().litellm.extra_headers)
if not isinstance(litellm_extra_headers, dict):
raise ValueError("LITELLM.EXTRA_HEADERS must be a JSON object")
except json.JSONDecodeError as e:
raise ValueError(f"LITELLM.EXTRA_HEADERS contains invalid JSON: {str(e)}")
kwargs["extra_headers"] = litellm_extra_headers
get_logger().debug("Prompts", artifact={"system": system, "user": user}) get_logger().debug("Prompts", artifact={"system": system, "user": user})
if get_settings().config.verbosity_level >= 2: if get_settings().config.verbosity_level >= 2:

View File

@ -4,6 +4,7 @@ import openai
from openai import APIError, AsyncOpenAI, RateLimitError, Timeout from openai import APIError, AsyncOpenAI, RateLimitError, Timeout
from retry import retry 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.config_loader import get_settings
from pr_agent.log import get_logger from pr_agent.log import get_logger
@ -41,7 +42,6 @@ class OpenAIHandler(BaseAiHandler):
tries=OPENAI_RETRIES, delay=2, backoff=2, jitter=(1, 3)) tries=OPENAI_RETRIES, delay=2, backoff=2, jitter=(1, 3))
async def chat_completion(self, model: str, system: str, user: str, temperature: float = 0.2): async def chat_completion(self, model: str, system: str, user: str, temperature: float = 0.2):
try: try:
deployment_id = self.deployment_id
get_logger().info("System: ", system) get_logger().info("System: ", system)
get_logger().info("User: ", user) get_logger().info("User: ", user)
messages = [{"role": "system", "content": system}, {"role": "user", "content": user}] messages = [{"role": "system", "content": system}, {"role": "user", "content": user}]

34
pr_agent/algo/cli_args.py Normal file
View File

@ -0,0 +1,34 @@
from base64 import b64decode
import hashlib
class CliArgs:
@staticmethod
def validate_user_args(args: list) -> (bool, str):
try:
if not args:
return True, ""
# decode forbidden args
_encoded_args = 'ZW5hYmxlX2F1dG9fYXBwcm92YWw=:YXBwcm92ZV9wcl9vbl9zZWxmX3Jldmlldw==:YmFzZV91cmw=:dXJs:YXBwX25hbWU=:c2VjcmV0X3Byb3ZpZGVy:Z2l0X3Byb3ZpZGVy:c2tpcF9rZXlz:b3BlbmFpLmtleQ==:QU5BTFlUSUNTX0ZPTERFUg==:dXJp:YXBwX2lk:d2ViaG9va19zZWNyZXQ=:YmVhcmVyX3Rva2Vu:UEVSU09OQUxfQUNDRVNTX1RPS0VO:b3ZlcnJpZGVfZGVwbG95bWVudF90eXBl:cHJpdmF0ZV9rZXk=:bG9jYWxfY2FjaGVfcGF0aA==:ZW5hYmxlX2xvY2FsX2NhY2hl:amlyYV9iYXNlX3VybA==:YXBpX2Jhc2U=:YXBpX3R5cGU=:YXBpX3ZlcnNpb24=:c2tpcF9rZXlz'
forbidden_cli_args = []
for e in _encoded_args.split(':'):
forbidden_cli_args.append(b64decode(e).decode())
# lowercase all forbidden args
for i, _ in enumerate(forbidden_cli_args):
forbidden_cli_args[i] = forbidden_cli_args[i].lower()
if '.' not in forbidden_cli_args[i]:
forbidden_cli_args[i] = '.' + forbidden_cli_args[i]
for arg in args:
if arg.startswith('--'):
arg_word = arg.lower()
arg_word = arg_word.replace('__', '.') # replace double underscore with dot, e.g. --openai__key -> --openai.key
for forbidden_arg_word in forbidden_cli_args:
if forbidden_arg_word in arg_word:
return False, forbidden_arg_word
return True, ""
except Exception as e:
return False, str(e)

View File

@ -3,17 +3,18 @@ from __future__ import annotations
import re import re
import traceback import traceback
from pr_agent.config_loader import get_settings
from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo
from pr_agent.config_loader import get_settings
from pr_agent.log import get_logger from pr_agent.log import get_logger
def extend_patch(original_file_str, patch_str, patch_extra_lines_before=0, def extend_patch(original_file_str, patch_str, patch_extra_lines_before=0,
patch_extra_lines_after=0, filename: str = "") -> str: patch_extra_lines_after=0, filename: str = "", new_file_str="") -> str:
if not patch_str or (patch_extra_lines_before == 0 and patch_extra_lines_after == 0) or not original_file_str: if not patch_str or (patch_extra_lines_before == 0 and patch_extra_lines_after == 0) or not original_file_str:
return patch_str return patch_str
original_file_str = decode_if_bytes(original_file_str) original_file_str = decode_if_bytes(original_file_str)
new_file_str = decode_if_bytes(new_file_str)
if not original_file_str: if not original_file_str:
return patch_str return patch_str
@ -22,7 +23,7 @@ def extend_patch(original_file_str, patch_str, patch_extra_lines_before=0,
try: try:
extended_patch_str = process_patch_lines(patch_str, original_file_str, extended_patch_str = process_patch_lines(patch_str, original_file_str,
patch_extra_lines_before, patch_extra_lines_after) patch_extra_lines_before, patch_extra_lines_after, new_file_str)
except Exception as e: except Exception as e:
get_logger().warning(f"Failed to extend patch: {e}", artifact={"traceback": traceback.format_exc()}) get_logger().warning(f"Failed to extend patch: {e}", artifact={"traceback": traceback.format_exc()})
return patch_str return patch_str
@ -31,7 +32,7 @@ def extend_patch(original_file_str, patch_str, patch_extra_lines_before=0,
def decode_if_bytes(original_file_str): def decode_if_bytes(original_file_str):
if isinstance(original_file_str, bytes): if isinstance(original_file_str, (bytes, bytearray)):
try: try:
return original_file_str.decode('utf-8') return original_file_str.decode('utf-8')
except UnicodeDecodeError: except UnicodeDecodeError:
@ -52,32 +53,36 @@ def should_skip_patch(filename):
return False return False
def process_patch_lines(patch_str, original_file_str, patch_extra_lines_before, patch_extra_lines_after): def process_patch_lines(patch_str, original_file_str, patch_extra_lines_before, patch_extra_lines_after, new_file_str=""):
allow_dynamic_context = get_settings().config.allow_dynamic_context allow_dynamic_context = get_settings().config.allow_dynamic_context
patch_extra_lines_before_dynamic = get_settings().config.max_extra_lines_before_dynamic_context patch_extra_lines_before_dynamic = get_settings().config.max_extra_lines_before_dynamic_context
original_lines = original_file_str.splitlines() file_original_lines = original_file_str.splitlines()
len_original_lines = len(original_lines) file_new_lines = new_file_str.splitlines() if new_file_str else []
len_original_lines = len(file_original_lines)
patch_lines = patch_str.splitlines() patch_lines = patch_str.splitlines()
extended_patch_lines = [] extended_patch_lines = []
is_valid_hunk = True
start1, size1, start2, size2 = -1, -1, -1, -1 start1, size1, start2, size2 = -1, -1, -1, -1
RE_HUNK_HEADER = re.compile( RE_HUNK_HEADER = re.compile(
r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@[ ]?(.*)") r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@[ ]?(.*)")
try: try:
for line in patch_lines: for i,line in enumerate(patch_lines):
if line.startswith('@@'): if line.startswith('@@'):
match = RE_HUNK_HEADER.match(line) match = RE_HUNK_HEADER.match(line)
# identify hunk header # identify hunk header
if match: if match:
# finish processing previous hunk # finish processing previous hunk
if start1 != -1 and patch_extra_lines_after > 0: if is_valid_hunk and (start1 != -1 and patch_extra_lines_after > 0):
delta_lines = [f' {line}' for line in original_lines[start1 + size1 - 1:start1 + size1 - 1 + patch_extra_lines_after]] delta_lines_original = [f' {line}' for line in file_original_lines[start1 + size1 - 1:start1 + size1 - 1 + patch_extra_lines_after]]
extended_patch_lines.extend(delta_lines) extended_patch_lines.extend(delta_lines_original)
section_header, size1, size2, start1, start2 = extract_hunk_headers(match) section_header, size1, size2, start1, start2 = extract_hunk_headers(match)
if patch_extra_lines_before > 0 or patch_extra_lines_after > 0: is_valid_hunk = check_if_hunk_lines_matches_to_file(i, file_original_lines, patch_lines, start1)
if is_valid_hunk and (patch_extra_lines_before > 0 or patch_extra_lines_after > 0):
def _calc_context_limits(patch_lines_before): def _calc_context_limits(patch_lines_before):
extended_start1 = max(1, start1 - patch_lines_before) extended_start1 = max(1, start1 - patch_lines_before)
extended_size1 = size1 + (start1 - extended_start1) + patch_extra_lines_after extended_size1 = size1 + (start1 - extended_start1) + patch_extra_lines_after
@ -90,12 +95,15 @@ def process_patch_lines(patch_str, original_file_str, patch_extra_lines_before,
extended_size2 = max(extended_size2 - delta_cap, size2) extended_size2 = max(extended_size2 - delta_cap, size2)
return extended_start1, extended_size1, extended_start2, extended_size2 return extended_start1, extended_size1, extended_start2, extended_size2
if allow_dynamic_context: if allow_dynamic_context and file_new_lines:
extended_start1, extended_size1, extended_start2, extended_size2 = \ extended_start1, extended_size1, extended_start2, extended_size2 = \
_calc_context_limits(patch_extra_lines_before_dynamic) _calc_context_limits(patch_extra_lines_before_dynamic)
lines_before = original_lines[extended_start1 - 1:start1 - 1]
lines_before_original = file_original_lines[extended_start1 - 1:start1 - 1]
lines_before_new = file_new_lines[extended_start2 - 1:start2 - 1]
found_header = False found_header = False
for i, line, in enumerate(lines_before): if lines_before_original == lines_before_new: # Making sure no changes from a previous hunk
for i, line, in enumerate(lines_before_original):
if section_header in line: if section_header in line:
found_header = True found_header = True
# Update start and size in one line each # Update start and size in one line each
@ -104,6 +112,11 @@ def process_patch_lines(patch_str, original_file_str, patch_extra_lines_before,
# get_logger().debug(f"Found section header in line {i} before the hunk") # get_logger().debug(f"Found section header in line {i} before the hunk")
section_header = '' section_header = ''
break break
else:
get_logger().debug(f"Extra lines before hunk are different in original and new file - dynamic context",
artifact={"lines_before_original": lines_before_original,
"lines_before_new": lines_before_new})
if not found_header: if not found_header:
# get_logger().debug(f"Section header not found in the extra lines before the hunk") # get_logger().debug(f"Section header not found in the extra lines before the hunk")
extended_start1, extended_size1, extended_start2, extended_size2 = \ extended_start1, extended_size1, extended_start2, extended_size2 = \
@ -112,11 +125,23 @@ def process_patch_lines(patch_str, original_file_str, patch_extra_lines_before,
extended_start1, extended_size1, extended_start2, extended_size2 = \ extended_start1, extended_size1, extended_start2, extended_size2 = \
_calc_context_limits(patch_extra_lines_before) _calc_context_limits(patch_extra_lines_before)
delta_lines = [f' {line}' for line in original_lines[extended_start1 - 1:start1 - 1]] # check if extra lines before hunk are different in original and new file
delta_lines_original = [f' {line}' for line in file_original_lines[extended_start1 - 1:start1 - 1]]
if file_new_lines:
delta_lines_new = [f' {line}' for line in file_new_lines[extended_start2 - 1:start2 - 1]]
if delta_lines_original != delta_lines_new:
get_logger().debug(f"Extra lines before hunk are different in original and new file",
artifact={"delta_lines_original": delta_lines_original,
"delta_lines_new": delta_lines_new})
extended_start1 = start1
extended_size1 = size1
extended_start2 = start2
extended_size2 = size2
delta_lines_original = []
# logic to remove section header if its in the extra delta lines (in dynamic context, this is also done) # logic to remove section header if its in the extra delta lines (in dynamic context, this is also done)
if section_header and not allow_dynamic_context: if section_header and not allow_dynamic_context:
for line in delta_lines: for line in delta_lines_original:
if section_header in line: if section_header in line:
section_header = '' # remove section header if it is in the extra delta lines section_header = '' # remove section header if it is in the extra delta lines
break break
@ -125,12 +150,12 @@ def process_patch_lines(patch_str, original_file_str, patch_extra_lines_before,
extended_size1 = size1 extended_size1 = size1
extended_start2 = start2 extended_start2 = start2
extended_size2 = size2 extended_size2 = size2
delta_lines = [] delta_lines_original = []
extended_patch_lines.append('') extended_patch_lines.append('')
extended_patch_lines.append( extended_patch_lines.append(
f'@@ -{extended_start1},{extended_size1} ' f'@@ -{extended_start1},{extended_size1} '
f'+{extended_start2},{extended_size2} @@ {section_header}') f'+{extended_start2},{extended_size2} @@ {section_header}')
extended_patch_lines.extend(delta_lines) # one to zero based extended_patch_lines.extend(delta_lines_original) # one to zero based
continue continue
extended_patch_lines.append(line) extended_patch_lines.append(line)
except Exception as e: except Exception as e:
@ -138,15 +163,41 @@ def process_patch_lines(patch_str, original_file_str, patch_extra_lines_before,
return patch_str return patch_str
# finish processing last hunk # finish processing last hunk
if start1 != -1 and patch_extra_lines_after > 0: if start1 != -1 and patch_extra_lines_after > 0 and is_valid_hunk:
delta_lines = original_lines[start1 + size1 - 1:start1 + size1 - 1 + patch_extra_lines_after] delta_lines_original = file_original_lines[start1 + size1 - 1:start1 + size1 - 1 + patch_extra_lines_after]
# add space at the beginning of each extra line # add space at the beginning of each extra line
delta_lines = [f' {line}' for line in delta_lines] delta_lines_original = [f' {line}' for line in delta_lines_original]
extended_patch_lines.extend(delta_lines) extended_patch_lines.extend(delta_lines_original)
extended_patch_str = '\n'.join(extended_patch_lines) extended_patch_str = '\n'.join(extended_patch_lines)
return extended_patch_str return extended_patch_str
def check_if_hunk_lines_matches_to_file(i, original_lines, patch_lines, start1):
"""
Check if the hunk lines match the original file content. We saw cases where the hunk header line doesn't match the original file content, and then
extending the hunk with extra lines before the hunk header can cause the hunk to be invalid.
"""
is_valid_hunk = True
try:
if i + 1 < len(patch_lines) and patch_lines[i + 1][0] == ' ': # an existing line in the file
if patch_lines[i + 1].strip() != original_lines[start1 - 1].strip():
# check if different encoding is needed
original_line = original_lines[start1 - 1].strip()
for encoding in ['iso-8859-1', 'latin-1', 'ascii', 'utf-16']:
try:
if original_line.encode(encoding).decode().strip() == patch_lines[i + 1].strip():
get_logger().info(f"Detected different encoding in hunk header line {start1}, needed encoding: {encoding}")
return False # we still want to avoid extending the hunk. But we don't want to log an error
except:
pass
is_valid_hunk = False
get_logger().info(
f"Invalid hunk in PR, line {start1} in hunk header doesn't match the original file content")
except:
pass
return is_valid_hunk
def extract_hunk_headers(match): def extract_hunk_headers(match):
res = list(match.groups()) res = list(match.groups())
@ -268,7 +319,7 @@ __old hunk__
""" """
# if the file was deleted, return a message indicating that the file was deleted # if the file was deleted, return a message indicating that the file was deleted
if hasattr(file, 'edit_type') and file.edit_type == EDIT_TYPE.DELETED: if hasattr(file, 'edit_type') and file.edit_type == EDIT_TYPE.DELETED:
return f"\n\n## file '{file.filename.strip()}' was deleted\n" return f"\n\n## File '{file.filename.strip()}' was deleted\n"
patch_with_lines_str = f"\n\n## File: '{file.filename.strip()}'\n" patch_with_lines_str = f"\n\n## File: '{file.filename.strip()}'\n"
patch_lines = patch.splitlines() patch_lines = patch.splitlines()
@ -343,8 +394,8 @@ __old hunk__
return patch_with_lines_str.rstrip() return patch_with_lines_str.rstrip()
def extract_hunk_lines_from_patch(patch: str, file_name, line_start, line_end, side) -> tuple[str, str]: def extract_hunk_lines_from_patch(patch: str, file_name, line_start, line_end, side, remove_trailing_chars: bool = True) -> tuple[str, str]:
try:
patch_with_lines_str = f"\n\n## File: '{file_name.strip()}'\n\n" patch_with_lines_str = f"\n\n## File: '{file_name.strip()}'\n\n"
selected_lines = "" selected_lines = ""
patch_lines = patch.splitlines() patch_lines = patch.splitlines()
@ -387,5 +438,12 @@ def extract_hunk_lines_from_patch(patch: str, file_name, line_start, line_end, s
patch_with_lines_str += line + '\n' patch_with_lines_str += line + '\n'
if not line.startswith('-'): # currently we don't support /ask line for deleted lines if not line.startswith('-'): # currently we don't support /ask line for deleted lines
selected_lines_num += 1 selected_lines_num += 1
except Exception as e:
get_logger().error(f"Failed to extract hunk lines from patch: {e}", artifact={"traceback": traceback.format_exc()})
return "", ""
return patch_with_lines_str.rstrip(), selected_lines.rstrip() if remove_trailing_chars:
patch_with_lines_str = patch_with_lines_str.rstrip()
selected_lines = selected_lines.rstrip()
return patch_with_lines_str, selected_lines

View File

@ -4,8 +4,6 @@ from typing import Dict
from pr_agent.config_loader import get_settings from pr_agent.config_loader import get_settings
def filter_bad_extensions(files): def filter_bad_extensions(files):
# Bad Extensions, source: https://github.com/EleutherAI/github-downloader/blob/345e7c4cbb9e0dc8a0615fd995a08bf9d73b3fe6/download_repo_text.py # noqa: E501 # Bad Extensions, source: https://github.com/EleutherAI/github-downloader/blob/345e7c4cbb9e0dc8a0615fd995a08bf9d73b3fe6/download_repo_text.py # noqa: E501
bad_extensions = get_settings().bad_extensions.default bad_extensions = get_settings().bad_extensions.default

View File

@ -5,14 +5,15 @@ from typing import Callable, List, Tuple
from github import RateLimitExceededException 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.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.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, get_weak_model
from pr_agent.config_loader import get_settings from pr_agent.config_loader import get_settings
from pr_agent.git_providers.git_provider import GitProvider from pr_agent.git_providers.git_provider import GitProvider
from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo
from pr_agent.log import get_logger from pr_agent.log import get_logger
DELETED_FILES_ = "Deleted files:\n" DELETED_FILES_ = "Deleted files:\n"
@ -194,20 +195,23 @@ def pr_generate_extended_diff(pr_languages: list,
for lang in pr_languages: for lang in pr_languages:
for file in lang['files']: for file in lang['files']:
original_file_content_str = file.base_file original_file_content_str = file.base_file
new_file_content_str = file.head_file
patch = file.patch patch = file.patch
if not patch: if not patch:
continue continue
# extend each patch with extra lines of context # extend each patch with extra lines of context
extended_patch = extend_patch(original_file_content_str, patch, extended_patch = extend_patch(original_file_content_str, patch,
patch_extra_lines_before, patch_extra_lines_after, file.filename) patch_extra_lines_before, patch_extra_lines_after, file.filename,
new_file_str=new_file_content_str)
if not extended_patch: if not extended_patch:
get_logger().warning(f"Failed to extend patch for file: {file.filename}") get_logger().warning(f"Failed to extend patch for file: {file.filename}")
continue continue
full_extended_patch = f"\n\n## {file.filename}\n{extended_patch.rstrip()}\n"
if add_line_numbers_to_hunks: if add_line_numbers_to_hunks:
full_extended_patch = convert_to_hunks_with_lines_numbers(extended_patch, file) full_extended_patch = convert_to_hunks_with_lines_numbers(extended_patch, file)
else:
full_extended_patch = f"\n\n## File: '{file.filename.strip()}'\n{extended_patch.rstrip()}\n"
# add AI-summary metadata to the patch # add AI-summary metadata to the patch
if file.ai_file_summary and get_settings().get("config.enable_ai_metadata", False): if file.ai_file_summary and get_settings().get("config.enable_ai_metadata", False):
@ -315,13 +319,13 @@ def generate_full_patch(convert_hunks_to_line_numbers, file_dict, max_tokens_mod
# TODO: Option for alternative logic to remove hunks from the patch to reduce the number of tokens # TODO: Option for alternative logic to remove hunks from the patch to reduce the number of tokens
# until we meet the requirements # until we meet the requirements
if get_settings().config.verbosity_level >= 2: if get_settings().config.verbosity_level >= 2:
get_logger().warning(f"Patch too large, skipping it, {filename}") get_logger().warning(f"Patch too large, skipping it: '{filename}'")
remaining_files_list_new.append(filename) remaining_files_list_new.append(filename)
continue continue
if patch: if patch:
if not convert_hunks_to_line_numbers: if not convert_hunks_to_line_numbers:
patch_final = f"\n\n## File: '{filename.strip()}\n\n{patch.strip()}\n'" patch_final = f"\n\n## File: '{filename.strip()}'\n\n{patch.strip()}\n"
else: else:
patch_final = "\n\n" + patch.strip() patch_final = "\n\n" + patch.strip()
patches.append(patch_final) patches.append(patch_final)
@ -353,8 +357,8 @@ async def retry_with_fallback_models(f: Callable, model_type: ModelType = ModelT
def _get_all_models(model_type: ModelType = ModelType.REGULAR) -> List[str]: def _get_all_models(model_type: ModelType = ModelType.REGULAR) -> List[str]:
if model_type == ModelType.TURBO: if model_type == ModelType.WEAK:
model = get_settings().config.model_turbo model = get_weak_model()
else: else:
model = get_settings().config.model model = get_settings().config.model
fallback_models = get_settings().config.fallback_models fallback_models = get_settings().config.fallback_models
@ -382,7 +386,8 @@ def _get_all_deployments(all_models: List[str]) -> List[str]:
def get_pr_multi_diffs(git_provider: GitProvider, def get_pr_multi_diffs(git_provider: GitProvider,
token_handler: TokenHandler, token_handler: TokenHandler,
model: str, model: str,
max_calls: int = 5) -> List[str]: max_calls: int = 5,
add_line_numbers: bool = True) -> List[str]:
""" """
Retrieves the diff files from a Git provider, sorts them by main language, and generates patches for each file. Retrieves the diff files from a Git provider, sorts them by main language, and generates patches for each file.
The patches are split into multiple groups based on the maximum number of tokens allowed for the given model. The patches are split into multiple groups based on the maximum number of tokens allowed for the given model.
@ -423,7 +428,8 @@ def get_pr_multi_diffs(git_provider: GitProvider,
# try first a single run with standard diff string, with patch extension, and no deletions # try first a single run with standard diff string, with patch extension, and no deletions
patches_extended, total_tokens, patches_extended_tokens = pr_generate_extended_diff( patches_extended, total_tokens, patches_extended_tokens = pr_generate_extended_diff(
pr_languages, token_handler, add_line_numbers_to_hunks=True, pr_languages, token_handler,
add_line_numbers_to_hunks=add_line_numbers,
patch_extra_lines_before=PATCH_EXTRA_LINES_BEFORE, patch_extra_lines_before=PATCH_EXTRA_LINES_BEFORE,
patch_extra_lines_after=PATCH_EXTRA_LINES_AFTER) patch_extra_lines_after=PATCH_EXTRA_LINES_AFTER)
@ -452,7 +458,12 @@ def get_pr_multi_diffs(git_provider: GitProvider,
if patch is None: if patch is None:
continue continue
# Add line numbers and metadata to the patch
if add_line_numbers:
patch = convert_to_hunks_with_lines_numbers(patch, file) patch = convert_to_hunks_with_lines_numbers(patch, file)
else:
patch = f"\n\n## File: '{file.filename.strip()}'\n\n{patch.strip()}\n"
# add AI-summary metadata to the patch # add AI-summary metadata to the patch
if file.ai_file_summary and get_settings().get("config.enable_ai_metadata", False): if file.ai_file_summary and get_settings().get("config.enable_ai_metadata", False):
patch = add_ai_summary_top_patch(file, patch) patch = add_ai_summary_top_patch(file, patch)

View File

@ -1,8 +1,9 @@
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 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 pr_agent.log import get_logger from pr_agent.log import get_logger

View File

@ -1,5 +1,6 @@
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum from enum import Enum
from typing import Optional
class EDIT_TYPE(Enum): class EDIT_TYPE(Enum):
@ -21,4 +22,5 @@ class FilePatchInfo:
old_filename: str = None old_filename: str = None
num_plus_lines: int = -1 num_plus_lines: int = -1
num_minus_lines: int = -1 num_minus_lines: int = -1
language: Optional[str] = None
ai_file_summary: str = None ai_file_summary: str = None

View File

@ -7,14 +7,15 @@ import html
import json import json
import os import os
import re import re
import sys
import textwrap import textwrap
import time import time
import traceback import traceback
from datetime import datetime from datetime import datetime
from enum import Enum from enum import Enum
from importlib.metadata import PackageNotFoundError, version
from typing import Any, List, Tuple from typing import Any, List, Tuple
import html2text import html2text
import requests import requests
import yaml import yaml
@ -22,11 +23,19 @@ from pydantic import BaseModel
from starlette_context import context from starlette_context import context
from pr_agent.algo import MAX_TOKENS from pr_agent.algo import MAX_TOKENS
from pr_agent.algo.git_patch_processing import extract_hunk_lines_from_patch
from pr_agent.algo.token_handler import TokenEncoder 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.algo.types import FilePatchInfo
from pr_agent.config_loader import get_settings, global_settings
from pr_agent.log import get_logger from pr_agent.log import get_logger
def get_weak_model() -> str:
if get_settings().get("config.model_weak"):
return get_settings().config.model_weak
return get_settings().config.model
class Range(BaseModel): class Range(BaseModel):
line_start: int # should be 0-indexed line_start: int # should be 0-indexed
line_end: int line_end: int
@ -35,13 +44,17 @@ class Range(BaseModel):
class ModelType(str, Enum): class ModelType(str, Enum):
REGULAR = "regular" REGULAR = "regular"
TURBO = "turbo" WEAK = "weak"
class PRReviewHeader(str, Enum): class PRReviewHeader(str, Enum):
REGULAR = "## PR Reviewer Guide" REGULAR = "## PR Reviewer Guide"
INCREMENTAL = "## Incremental PR Reviewer Guide" INCREMENTAL = "## Incremental PR Reviewer Guide"
class ReasoningEffort(str, Enum):
HIGH = "high"
MEDIUM = "medium"
LOW = "low"
class PRDescriptionHeader(str, Enum): class PRDescriptionHeader(str, Enum):
CHANGES_WALKTHROUGH = "### **Changes walkthrough** 📝" CHANGES_WALKTHROUGH = "### **Changes walkthrough** 📝"
@ -97,7 +110,8 @@ def unique_strings(input_list: List[str]) -> List[str]:
def convert_to_markdown_v2(output_data: dict, def convert_to_markdown_v2(output_data: dict,
gfm_supported: bool = True, gfm_supported: bool = True,
incremental_review=None, incremental_review=None,
git_provider=None) -> str: git_provider=None,
files=None) -> str:
""" """
Convert a dictionary of data into markdown format. Convert a dictionary of data into markdown format.
Args: Args:
@ -173,7 +187,7 @@ def convert_to_markdown_v2(output_data: dict,
if is_value_no(value): if is_value_no(value):
markdown_text += f'### {emoji} No relevant tests\n\n' markdown_text += f'### {emoji} No relevant tests\n\n'
else: else:
markdown_text += f"### PR contains tests\n\n" markdown_text += f"### {emoji} PR contains tests\n\n"
elif 'ticket compliance check' in key_nice.lower(): elif 'ticket compliance check' in key_nice.lower():
markdown_text = ticket_markdown_logic(emoji, markdown_text, value, gfm_supported) markdown_text = ticket_markdown_logic(emoji, markdown_text, value, gfm_supported)
elif 'security concerns' in key_nice.lower(): elif 'security concerns' in key_nice.lower():
@ -221,15 +235,31 @@ def convert_to_markdown_v2(output_data: dict,
continue continue
relevant_file = issue.get('relevant_file', '').strip() relevant_file = issue.get('relevant_file', '').strip()
issue_header = issue.get('issue_header', '').strip() issue_header = issue.get('issue_header', '').strip()
if issue_header.lower() == 'possible bug':
issue_header = 'Possible Issue' # Make the header less frightening
issue_content = issue.get('issue_content', '').strip() issue_content = issue.get('issue_content', '').strip()
start_line = int(str(issue.get('start_line', 0)).strip()) start_line = int(str(issue.get('start_line', 0)).strip())
end_line = int(str(issue.get('end_line', 0)).strip()) end_line = int(str(issue.get('end_line', 0)).strip())
relevant_lines_str = extract_relevant_lines_str(end_line, files, relevant_file, start_line, dedent=True)
if git_provider:
reference_link = git_provider.get_line_link(relevant_file, start_line, end_line) reference_link = git_provider.get_line_link(relevant_file, start_line, end_line)
else:
reference_link = None
if gfm_supported: if gfm_supported:
if reference_link is not None and len(reference_link) > 0:
if relevant_lines_str:
issue_str = f"<details><summary><a href='{reference_link}'><strong>{issue_header}</strong></a>\n\n{issue_content}\n</summary>\n\n{relevant_lines_str}\n\n</details>"
else:
issue_str = f"<a href='{reference_link}'><strong>{issue_header}</strong></a><br>{issue_content}" issue_str = f"<a href='{reference_link}'><strong>{issue_header}</strong></a><br>{issue_content}"
else: else:
issue_str = f"<strong>{issue_header}</strong><br>{issue_content}"
else:
if reference_link is not None and len(reference_link) > 0:
issue_str = f"[**{issue_header}**]({reference_link})\n\n{issue_content}\n\n" issue_str = f"[**{issue_header}**]({reference_link})\n\n{issue_content}\n\n"
else:
issue_str = f"**{issue_header}**\n\n{issue_content}\n\n"
markdown_text += f"{issue_str}\n\n" markdown_text += f"{issue_str}\n\n"
except Exception as e: except Exception as e:
get_logger().exception(f"Failed to process 'Recommended focus areas for review': {e}") get_logger().exception(f"Failed to process 'Recommended focus areas for review': {e}")
@ -246,68 +276,143 @@ def convert_to_markdown_v2(output_data: dict,
if gfm_supported: if gfm_supported:
markdown_text += "</table>\n" markdown_text += "</table>\n"
if 'code_feedback' in output_data:
if gfm_supported:
markdown_text += f"\n\n"
markdown_text += f"<details><summary> <strong>Code feedback:</strong></summary>\n\n"
markdown_text += "<hr>"
else:
markdown_text += f"\n\n### Code feedback:\n\n"
for i, value in enumerate(output_data['code_feedback']):
if value is None or value == '' or value == {} or value == []:
continue
markdown_text += parse_code_suggestion(value, i, gfm_supported)+"\n\n"
if markdown_text.endswith('<hr>'):
markdown_text= markdown_text[:-4]
if gfm_supported:
markdown_text += f"</details>"
return markdown_text return markdown_text
def extract_relevant_lines_str(end_line, files, relevant_file, start_line, dedent=False) -> str:
"""
Finds 'relevant_file' in 'files', and extracts the lines from 'start_line' to 'end_line' string from the file content.
"""
try:
relevant_lines_str = ""
if files:
files = set_file_languages(files)
for file in files:
if file.filename.strip() == relevant_file:
if not file.head_file:
# as a fallback, extract relevant lines directly from patch
patch = file.patch
get_logger().info(f"No content found in file: '{file.filename}' for 'extract_relevant_lines_str'. Using patch instead")
_, selected_lines = extract_hunk_lines_from_patch(patch, file.filename, start_line, end_line,side='right')
if not selected_lines:
get_logger().error(f"Failed to extract relevant lines from patch: {file.filename}")
return ""
# filter out '-' lines
relevant_lines_str = ""
for line in selected_lines.splitlines():
if line.startswith('-'):
continue
relevant_lines_str += line[1:] + '\n'
else:
relevant_file_lines = file.head_file.splitlines()
relevant_lines_str = "\n".join(relevant_file_lines[start_line - 1:end_line])
if dedent and relevant_lines_str:
# Remove the longest leading string of spaces and tabs common to all lines.
relevant_lines_str = textwrap.dedent(relevant_lines_str)
relevant_lines_str = f"```{file.language}\n{relevant_lines_str}\n```"
break
return relevant_lines_str
except Exception as e:
get_logger().exception(f"Failed to extract relevant lines: {e}")
return ""
def ticket_markdown_logic(emoji, markdown_text, value, gfm_supported) -> str: def ticket_markdown_logic(emoji, markdown_text, value, gfm_supported) -> str:
ticket_compliance_str = "" ticket_compliance_str = ""
final_compliance_level = -1 compliance_emoji = ''
# Track compliance levels across all tickets
all_compliance_levels = []
if isinstance(value, list): if isinstance(value, list):
for v in value: for ticket_analysis in value:
ticket_url = v.get('ticket_url', '').strip() try:
compliance_level = v.get('overall_compliance_level', '').strip() ticket_url = ticket_analysis.get('ticket_url', '').strip()
# add emojis, if 'Fully compliant' ✅, 'Partially compliant' 🔶, or 'Not compliant' ❌
if compliance_level.lower() == 'fully compliant':
# compliance_level = '✅ Fully compliant'
final_compliance_level = 2 if final_compliance_level == -1 else 1
elif compliance_level.lower() == 'partially compliant':
# compliance_level = '🔶 Partially compliant'
final_compliance_level = 1
elif compliance_level.lower() == 'not compliant':
# compliance_level = '❌ Not compliant'
final_compliance_level = 0 if final_compliance_level < 1 else 1
# explanation = v.get('compliance_analysis', '').strip()
explanation = '' explanation = ''
fully_compliant_str = v.get('fully_compliant_requirements', '').strip() ticket_compliance_level = '' # Individual ticket compliance
not_compliant_str = v.get('not_compliant_requirements', '').strip() fully_compliant_str = ticket_analysis.get('fully_compliant_requirements', '').strip()
not_compliant_str = ticket_analysis.get('not_compliant_requirements', '').strip()
requires_further_human_verification = ticket_analysis.get('requires_further_human_verification',
'').strip()
if not fully_compliant_str and not not_compliant_str:
get_logger().debug(f"Ticket compliance has no requirements",
artifact={'ticket_url': ticket_url})
continue
# Calculate individual ticket compliance level
if fully_compliant_str: if fully_compliant_str:
explanation += f"Fully compliant requirements:\n{fully_compliant_str}\n\n"
if not_compliant_str: if not_compliant_str:
explanation += f"Not compliant requirements:\n{not_compliant_str}\n\n" ticket_compliance_level = 'Partially compliant'
ticket_compliance_str += f"\n\n**[{ticket_url.split('/')[-1]}]({ticket_url}) - {compliance_level}**\n\n{explanation}\n\n"
if final_compliance_level == 2:
compliance_level = ''
elif final_compliance_level == 1:
compliance_level = '🔶'
else: else:
compliance_level = '' if not requires_further_human_verification:
ticket_compliance_level = 'Fully compliant'
else:
ticket_compliance_level = 'PR Code Verified'
elif not_compliant_str:
ticket_compliance_level = 'Not compliant'
# Store the compliance level for aggregation
if ticket_compliance_level:
all_compliance_levels.append(ticket_compliance_level)
# build compliance string
if fully_compliant_str:
explanation += f"Compliant requirements:\n\n{fully_compliant_str}\n\n"
if not_compliant_str:
explanation += f"Non-compliant requirements:\n\n{not_compliant_str}\n\n"
if requires_further_human_verification:
explanation += f"Requires further human verification:\n\n{requires_further_human_verification}\n\n"
ticket_compliance_str += f"\n\n**[{ticket_url.split('/')[-1]}]({ticket_url}) - {ticket_compliance_level}**\n\n{explanation}\n\n"
# for debugging
if requires_further_human_verification:
get_logger().debug(f"Ticket compliance requires further human verification",
artifact={'ticket_url': ticket_url,
'requires_further_human_verification': requires_further_human_verification,
'compliance_level': ticket_compliance_level})
except Exception as e:
get_logger().exception(f"Failed to process ticket compliance: {e}")
continue
# Calculate overall compliance level and emoji
if all_compliance_levels:
if all(level == 'Fully compliant' for level in all_compliance_levels):
compliance_level = 'Fully compliant'
compliance_emoji = ''
elif all(level == 'PR Code Verified' for level in all_compliance_levels):
compliance_level = 'PR Code Verified'
compliance_emoji = ''
elif any(level == 'Not compliant' for level in all_compliance_levels):
# If there's a mix of compliant and non-compliant tickets
if any(level in ['Fully compliant', 'PR Code Verified'] for level in all_compliance_levels):
compliance_level = 'Partially compliant'
compliance_emoji = '🔶'
else:
compliance_level = 'Not compliant'
compliance_emoji = ''
elif any(level == 'Partially compliant' for level in all_compliance_levels):
compliance_level = 'Partially compliant'
compliance_emoji = '🔶'
else:
compliance_level = 'PR Code Verified'
compliance_emoji = ''
# Set extra statistics outside the ticket loop
get_settings().set('config.extra_statistics', {'compliance_level': compliance_level})
# editing table row for ticket compliance analysis
if gfm_supported: if gfm_supported:
markdown_text += f"<tr><td>\n\n" markdown_text += f"<tr><td>\n\n"
markdown_text += f"**{emoji} Ticket compliance analysis {compliance_level}**\n\n" markdown_text += f"**{emoji} Ticket compliance analysis {compliance_emoji}**\n\n"
markdown_text += ticket_compliance_str markdown_text += ticket_compliance_str
markdown_text += f"</td></tr>\n" markdown_text += f"</td></tr>\n"
else: else:
markdown_text += f"### {emoji} Ticket compliance analysis {compliance_level}\n\n" markdown_text += f"### {emoji} Ticket compliance analysis {compliance_emoji}\n\n"
markdown_text += ticket_compliance_str+"\n\n" markdown_text += ticket_compliance_str + "\n\n"
return markdown_text return markdown_text
@ -534,27 +639,22 @@ def load_large_diff(filename, new_file_content_str: str, original_file_content_s
""" """
Generate a patch for a modified file by comparing the original content of the file with the new content provided as Generate a patch for a modified file by comparing the original content of the file with the new content provided as
input. input.
Args:
new_file_content_str: The new content of the file as a string.
original_file_content_str: The original content of the file as a string.
Returns:
The generated or provided patch string.
Raises:
None.
""" """
patch = "" if not original_file_content_str and not new_file_content_str:
return ""
try: try:
original_file_content_str = (original_file_content_str or "").rstrip() + "\n"
new_file_content_str = (new_file_content_str or "").rstrip() + "\n"
diff = difflib.unified_diff(original_file_content_str.splitlines(keepends=True), diff = difflib.unified_diff(original_file_content_str.splitlines(keepends=True),
new_file_content_str.splitlines(keepends=True)) new_file_content_str.splitlines(keepends=True))
if get_settings().config.verbosity_level >= 2 and show_warning: if get_settings().config.verbosity_level >= 2 and show_warning:
get_logger().warning(f"File was modified, but no patch was found. Manually creating patch: {filename}.") get_logger().info(f"File was modified, but no patch was found. Manually creating patch: {filename}.")
patch = ''.join(diff) patch = ''.join(diff)
except Exception:
pass
return patch return patch
except Exception as e:
get_logger().exception(f"Failed to generate patch for file: {filename}")
return ""
def update_settings_from_args(args: List[str]) -> List[str]: def update_settings_from_args(args: List[str]) -> List[str]:
@ -640,7 +740,7 @@ def try_fix_yaml(response_text: str,
get_logger().info(f"Successfully parsed AI prediction after adding |-\n") get_logger().info(f"Successfully parsed AI prediction after adding |-\n")
return data return data
except: except:
get_logger().info(f"Failed to parse AI prediction after adding |-\n") pass
# second fallback - try to extract only range from first ```yaml to ```` # second fallback - try to extract only range from first ```yaml to ````
snippet_pattern = r'```(yaml)?[\s\S]*?```' snippet_pattern = r'```(yaml)?[\s\S]*?```'
@ -684,9 +784,19 @@ def try_fix_yaml(response_text: str,
except: except:
pass pass
# fifth fallback - try to remove leading '+' (sometimes added by AI for 'existing code' and 'improved code')
response_text_lines_copy = response_text_lines.copy()
for i in range(0, len(response_text_lines_copy)):
if response_text_lines_copy[i].startswith('+'):
response_text_lines_copy[i] = ' ' + response_text_lines_copy[i][1:]
try:
data = yaml.safe_load('\n'.join(response_text_lines_copy))
get_logger().info(f"Successfully parsed AI prediction after removing leading '+'")
return data
except:
pass
# fifth fallback - try to remove last lines # sixth fallback - try to remove last lines
data = {}
for i in range(1, len(response_text_lines)): for i in range(1, len(response_text_lines)):
response_text_lines_tmp = '\n'.join(response_text_lines[:-i]) response_text_lines_tmp = '\n'.join(response_text_lines[:-i])
try: try:
@ -1097,3 +1207,48 @@ def process_description(description_full: str) -> Tuple[str, List]:
get_logger().exception(f"Failed to process description: {e}") get_logger().exception(f"Failed to process description: {e}")
return base_description_str, files return base_description_str, files
def get_version() -> str:
# First check pyproject.toml if running directly out of repository
if os.path.exists("pyproject.toml"):
if sys.version_info >= (3, 11):
import tomllib
with open("pyproject.toml", "rb") as f:
data = tomllib.load(f)
if "project" in data and "version" in data["project"]:
return data["project"]["version"]
else:
get_logger().warning("Version not found in pyproject.toml")
else:
get_logger().warning("Unable to determine local version from pyproject.toml")
# Otherwise get the installed pip package version
try:
return version('pr-agent')
except PackageNotFoundError:
get_logger().warning("Unable to find package named 'pr-agent'")
return "unknown"
def set_file_languages(diff_files) -> List[FilePatchInfo]:
try:
# if the language is already set, do not change it
if hasattr(diff_files[0], 'language') and diff_files[0].language:
return diff_files
# map file extensions to programming languages
language_extension_map_org = get_settings().language_extension_map_org
extension_to_language = {}
for language, extensions in language_extension_map_org.items():
for ext in extensions:
extension_to_language[ext] = language
for file in diff_files:
extension_s = '.' + file.filename.rsplit('.')[-1]
language_name = "txt"
if extension_s and (extension_s in extension_to_language):
language_name = extension_to_language[extension_s]
file.language = language_name.lower()
except Exception as e:
get_logger().exception(f"Failed to set file languages: {e}")
return diff_files

View File

@ -3,8 +3,9 @@ import asyncio
import os import os
from pr_agent.agent.pr_agent import PRAgent, commands from pr_agent.agent.pr_agent import PRAgent, commands
from pr_agent.algo.utils import get_version
from pr_agent.config_loader import get_settings 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") log_level = os.environ.get("LOG_LEVEL", "INFO")
setup_logger(log_level) setup_logger(log_level)
@ -45,6 +46,7 @@ def set_parser():
To edit any configuration parameter from 'configuration.toml', just add -config_path=<value>. To edit any configuration parameter from 'configuration.toml', just add -config_path=<value>.
For example: 'python cli.py --pr_url=... review --pr_reviewer.extra_instructions="focus on the file: ..."' For example: 'python cli.py --pr_url=... review --pr_reviewer.extra_instructions="focus on the file: ..."'
""") """)
parser.add_argument('--version', action='version', version=f'pr-agent {get_version()}')
parser.add_argument('--pr_url', type=str, help='The URL of the PR to review', default=None) parser.add_argument('--pr_url', type=str, help='The URL of the PR to review', default=None)
parser.add_argument('--issue_url', type=str, help='The URL of the Issue to review', default=None) parser.add_argument('--issue_url', type=str, help='The URL of the Issue to review', default=None)
parser.add_argument('command', type=str, help='The', choices=commands, default='review') parser.add_argument('command', type=str, help='The', choices=commands, default='review')

View File

@ -12,7 +12,6 @@ global_settings = Dynaconf(
envvar_prefix=False, envvar_prefix=False,
merge_enabled=True, merge_enabled=True,
settings_files=[join(current_dir, f) for f in [ settings_files=[join(current_dir, f) for f in [
"settings/.secrets.toml",
"settings/configuration.toml", "settings/configuration.toml",
"settings/ignore.toml", "settings/ignore.toml",
"settings/language_extensions.toml", "settings/language_extensions.toml",
@ -29,12 +28,13 @@ global_settings = Dynaconf(
"settings/pr_add_docs.toml", "settings/pr_add_docs.toml",
"settings/custom_labels.toml", "settings/custom_labels.toml",
"settings/pr_help_prompts.toml", "settings/pr_help_prompts.toml",
"settings/.secrets.toml",
"settings_prod/.secrets.toml", "settings_prod/.secrets.toml",
]] ]]
) )
def get_settings(): def get_settings(use_context=False):
""" """
Retrieves the current settings. Retrieves the current settings.

View File

@ -1,14 +1,16 @@
from starlette_context import context
from pr_agent.config_loader import get_settings 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_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.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.git_provider import GitProvider
from pr_agent.git_providers.github_provider import GithubProvider from pr_agent.git_providers.github_provider import GithubProvider
from pr_agent.git_providers.gitlab_provider import GitLabProvider from pr_agent.git_providers.gitlab_provider import GitLabProvider
from pr_agent.git_providers.local_git_provider import LocalGitProvider 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 = { _GIT_PROVIDERS = {
'github': GithubProvider, 'github': GithubProvider,

View File

@ -2,33 +2,33 @@ import os
from typing import Optional, Tuple from typing import Optional, Tuple
from urllib.parse import urlparse from urllib.parse import urlparse
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 ..config_loader import get_settings
from .git_provider import GitProvider
from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo 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 (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
AZURE_DEVOPS_AVAILABLE = True AZURE_DEVOPS_AVAILABLE = True
ADO_APP_CLIENT_DEFAULT_ID = "499b84ac-1321-427f-aa17-267ca6975798/.default" ADO_APP_CLIENT_DEFAULT_ID = "499b84ac-1321-427f-aa17-267ca6975798/.default"
MAX_PR_DESCRIPTION_AZURE_LENGTH = 4000-1 MAX_PR_DESCRIPTION_AZURE_LENGTH = 4000-1
try: try:
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from msrest.authentication import BasicAuthentication
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from azure.devops.connection import Connection from azure.devops.connection import Connection
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from azure.identity import DefaultAzureCredential from azure.devops.v7_1.git.models import (Comment, CommentThread,
# noinspection PyUnresolvedReferences
from azure.devops.v7_1.git.models import (
Comment,
CommentThread,
GitVersionDescriptor,
GitPullRequest, GitPullRequest,
GitPullRequestIterationChanges, GitPullRequestIterationChanges,
) GitVersionDescriptor)
# noinspection PyUnresolvedReferences
from azure.identity import DefaultAzureCredential
from msrest.authentication import BasicAuthentication
except ImportError: except ImportError:
AZURE_DEVOPS_AVAILABLE = False AZURE_DEVOPS_AVAILABLE = False
@ -67,14 +67,12 @@ class AzureDevopsProvider(GitProvider):
relevant_lines_end = suggestion['relevant_lines_end'] relevant_lines_end = suggestion['relevant_lines_end']
if not relevant_lines_start or relevant_lines_start == -1: if not relevant_lines_start or relevant_lines_start == -1:
if get_settings().config.verbosity_level >= 2: get_logger().warning(
get_logger().exception(
f"Failed to publish code suggestion, relevant_lines_start is {relevant_lines_start}") f"Failed to publish code suggestion, relevant_lines_start is {relevant_lines_start}")
continue continue
if relevant_lines_end < relevant_lines_start: if relevant_lines_end < relevant_lines_start:
if get_settings().config.verbosity_level >= 2: get_logger().warning(f"Failed to publish code suggestion, "
get_logger().exception(f"Failed to publish code suggestion, "
f"relevant_lines_end is {relevant_lines_end} and " f"relevant_lines_end is {relevant_lines_end} and "
f"relevant_lines_start is {relevant_lines_start}") f"relevant_lines_start is {relevant_lines_start}")
continue continue
@ -95,9 +93,11 @@ class AzureDevopsProvider(GitProvider):
"side": "RIGHT", "side": "RIGHT",
} }
post_parameters_list.append(post_parameters) post_parameters_list.append(post_parameters)
if not post_parameters_list:
return False
try:
for post_parameters in post_parameters_list: for post_parameters in post_parameters_list:
try:
comment = Comment(content=post_parameters["body"], comment_type=1) comment = Comment(content=post_parameters["body"], comment_type=1)
thread = CommentThread(comments=[comment], thread = CommentThread(comments=[comment],
thread_context={ thread_context={
@ -117,15 +117,11 @@ class AzureDevopsProvider(GitProvider):
repository_id=self.repo_slug, repository_id=self.repo_slug,
pull_request_id=self.pr_num pull_request_id=self.pr_num
) )
if get_settings().config.verbosity_level >= 2:
get_logger().info(
f"Published code suggestion on {self.pr_num} at {post_parameters['path']}"
)
return True
except Exception as e: except Exception as e:
if get_settings().config.verbosity_level >= 2: get_logger().warning(f"Azure failed to publish code suggestion, error: {e}")
get_logger().error(f"Failed to publish code suggestion, error: {e}") return True
return False
def get_pr_description_full(self) -> str: def get_pr_description_full(self) -> str:
return self.pr.description return self.pr.description
@ -187,6 +183,7 @@ class AzureDevopsProvider(GitProvider):
return True return True
def set_pr(self, pr_url: str): def set_pr(self, pr_url: str):
self.pr_url = pr_url
self.workspace_slug, self.repo_slug, self.pr_num = self._parse_pr_url(pr_url) self.workspace_slug, self.repo_slug, self.pr_num = self._parse_pr_url(pr_url)
self.pr = self._get_pr() self.pr = self._get_pr()
@ -330,13 +327,13 @@ class AzureDevopsProvider(GitProvider):
edit_type = EDIT_TYPE.ADDED edit_type = EDIT_TYPE.ADDED
elif diff_types[file] == "delete": elif diff_types[file] == "delete":
edit_type = EDIT_TYPE.DELETED edit_type = EDIT_TYPE.DELETED
elif diff_types[file] == "rename": elif "rename" in diff_types[file]: # diff_type can be `rename` | `edit, rename`
edit_type = EDIT_TYPE.RENAMED edit_type = EDIT_TYPE.RENAMED
version = GitVersionDescriptor( version = GitVersionDescriptor(
version=base_sha.commit_id, version_type="commit" version=base_sha.commit_id, version_type="commit"
) )
if edit_type == EDIT_TYPE.ADDED: if edit_type == EDIT_TYPE.ADDED or edit_type == EDIT_TYPE.RENAMED:
original_file_content_str = "" original_file_content_str = ""
else: else:
try: try:
@ -382,6 +379,9 @@ class AzureDevopsProvider(GitProvider):
return [] return []
def publish_comment(self, pr_comment: str, is_temporary: bool = False, thread_context=None): def publish_comment(self, pr_comment: str, is_temporary: bool = False, thread_context=None):
if is_temporary and not get_settings().config.publish_output_progress:
get_logger().debug(f"Skipping publish_comment for temporary comment: {pr_comment}")
return None
comment = Comment(content=pr_comment) comment = Comment(content=pr_comment)
thread = CommentThread(comments=[comment], thread_context=thread_context, status=5) thread = CommentThread(comments=[comment], thread_context=thread_context, status=5)
thread_response = self.azure_devops_client.create_thread( thread_response = self.azure_devops_client.create_thread(
@ -615,9 +615,11 @@ class AzureDevopsProvider(GitProvider):
return pr_id return pr_id
except Exception as e: except Exception as e:
if get_settings().config.verbosity_level >= 2: if get_settings().config.verbosity_level >= 2:
get_logger().error(f"Failed to get pr id, error: {e}") get_logger().info(f"Failed to get pr id, error: {e}")
return "" return ""
def publish_file_comments(self, file_comments: list) -> bool: def publish_file_comments(self, file_comments: list) -> bool:
pass pass
def get_line_link(self, relevant_file: str, relevant_line_start: int, relevant_line_end: int = None) -> str:
return self.pr_url+f"?_a=files&path={relevant_file}"

View File

@ -1,4 +1,6 @@
import difflib
import json import json
import re
from typing import Optional, Tuple from typing import Optional, Tuple
from urllib.parse import urlparse from urllib.parse import urlparse
@ -6,13 +8,14 @@ import requests
from atlassian.bitbucket import Cloud from atlassian.bitbucket import Cloud
from starlette_context import context 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.file_filter import filter_ignored
from ..algo.language_handler import is_valid_file from ..algo.language_handler import is_valid_file
from ..algo.utils import find_line_number_of_relevant_line_in_file from ..algo.utils import find_line_number_of_relevant_line_in_file
from ..config_loader import get_settings from ..config_loader import get_settings
from ..log import get_logger 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): def _gef_filename(diff):
@ -71,19 +74,33 @@ class BitbucketProvider(GitProvider):
post_parameters_list = [] post_parameters_list = []
for suggestion in code_suggestions: for suggestion in code_suggestions:
body = suggestion["body"] body = suggestion["body"]
original_suggestion = suggestion.get('original_suggestion', None) # needed for diff code
if original_suggestion:
try:
existing_code = original_suggestion['existing_code'].rstrip() + "\n"
improved_code = original_suggestion['improved_code'].rstrip() + "\n"
diff = difflib.unified_diff(existing_code.split('\n'),
improved_code.split('\n'), n=999)
patch_orig = "\n".join(diff)
patch = "\n".join(patch_orig.splitlines()[5:]).strip('\n')
diff_code = f"\n\n```diff\n{patch.rstrip()}\n```"
# replace ```suggestion ... ``` with diff_code, using regex:
body = re.sub(r'```suggestion.*?```', diff_code, body, flags=re.DOTALL)
except Exception as e:
get_logger().exception(f"Bitbucket failed to get diff code for publishing, error: {e}")
continue
relevant_file = suggestion["relevant_file"] relevant_file = suggestion["relevant_file"]
relevant_lines_start = suggestion["relevant_lines_start"] relevant_lines_start = suggestion["relevant_lines_start"]
relevant_lines_end = suggestion["relevant_lines_end"] relevant_lines_end = suggestion["relevant_lines_end"]
if not relevant_lines_start or relevant_lines_start == -1: if not relevant_lines_start or relevant_lines_start == -1:
if get_settings().config.verbosity_level >= 2:
get_logger().exception( get_logger().exception(
f"Failed to publish code suggestion, relevant_lines_start is {relevant_lines_start}" f"Failed to publish code suggestion, relevant_lines_start is {relevant_lines_start}"
) )
continue continue
if relevant_lines_end < relevant_lines_start: if relevant_lines_end < relevant_lines_start:
if get_settings().config.verbosity_level >= 2:
get_logger().exception( get_logger().exception(
f"Failed to publish code suggestion, " f"Failed to publish code suggestion, "
f"relevant_lines_end is {relevant_lines_end} and " f"relevant_lines_end is {relevant_lines_end} and "
@ -112,8 +129,7 @@ class BitbucketProvider(GitProvider):
self.publish_inline_comments(post_parameters_list) self.publish_inline_comments(post_parameters_list)
return True return True
except Exception as e: except Exception as e:
if get_settings().config.verbosity_level >= 2: get_logger().error(f"Bitbucket failed to publish code suggestion, error: {e}")
get_logger().error(f"Failed to publish code suggestion, error: {e}")
return False return False
def publish_file_comments(self, file_comments: list) -> bool: def publish_file_comments(self, file_comments: list) -> bool:
@ -309,6 +325,9 @@ class BitbucketProvider(GitProvider):
self.publish_comment(pr_comment) self.publish_comment(pr_comment)
def publish_comment(self, pr_comment: str, is_temporary: bool = False): def publish_comment(self, pr_comment: str, is_temporary: bool = False):
if is_temporary and not get_settings().config.publish_output_progress:
get_logger().debug(f"Skipping publish_comment for temporary comment: {pr_comment}")
return None
pr_comment = self.limit_output_characters(pr_comment, self.max_comment_length) pr_comment = self.limit_output_characters(pr_comment, self.max_comment_length)
comment = self.pr.comment(pr_comment) comment = self.pr.comment(pr_comment)
if is_temporary: if is_temporary:

View File

@ -1,16 +1,21 @@
from distutils.version import LooseVersion import difflib
from requests.exceptions import HTTPError import re
from packaging.version import parse as parse_version
from typing import Optional, Tuple from typing import Optional, Tuple
from urllib.parse import quote_plus, urlparse from urllib.parse import quote_plus, urlparse
from atlassian.bitbucket import Bitbucket from atlassian.bitbucket import Bitbucket
from requests.exceptions import HTTPError
from .git_provider import GitProvider from ..algo.git_patch_processing import decode_if_bytes
from ..algo.types import EDIT_TYPE, FilePatchInfo
from ..algo.language_handler import is_valid_file 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 ..config_loader import get_settings
from ..log import get_logger from ..log import get_logger
from .git_provider import GitProvider
class BitbucketServerProvider(GitProvider): class BitbucketServerProvider(GitProvider):
@ -35,7 +40,7 @@ class BitbucketServerProvider(GitProvider):
token=get_settings().get("BITBUCKET_SERVER.BEARER_TOKEN", token=get_settings().get("BITBUCKET_SERVER.BEARER_TOKEN",
None)) None))
try: try:
self.bitbucket_api_version = LooseVersion(self.bitbucket_client.get("rest/api/1.0/application-properties").get('version')) self.bitbucket_api_version = parse_version(self.bitbucket_client.get("rest/api/1.0/application-properties").get('version'))
except Exception: except Exception:
self.bitbucket_api_version = None self.bitbucket_api_version = None
@ -65,20 +70,33 @@ class BitbucketServerProvider(GitProvider):
post_parameters_list = [] post_parameters_list = []
for suggestion in code_suggestions: for suggestion in code_suggestions:
body = suggestion["body"] body = suggestion["body"]
original_suggestion = suggestion.get('original_suggestion', None) # needed for diff code
if original_suggestion:
try:
existing_code = original_suggestion['existing_code'].rstrip() + "\n"
improved_code = original_suggestion['improved_code'].rstrip() + "\n"
diff = difflib.unified_diff(existing_code.split('\n'),
improved_code.split('\n'), n=999)
patch_orig = "\n".join(diff)
patch = "\n".join(patch_orig.splitlines()[5:]).strip('\n')
diff_code = f"\n\n```diff\n{patch.rstrip()}\n```"
# replace ```suggestion ... ``` with diff_code, using regex:
body = re.sub(r'```suggestion.*?```', diff_code, body, flags=re.DOTALL)
except Exception as e:
get_logger().exception(f"Bitbucket failed to get diff code for publishing, error: {e}")
continue
relevant_file = suggestion["relevant_file"] relevant_file = suggestion["relevant_file"]
relevant_lines_start = suggestion["relevant_lines_start"] relevant_lines_start = suggestion["relevant_lines_start"]
relevant_lines_end = suggestion["relevant_lines_end"] relevant_lines_end = suggestion["relevant_lines_end"]
if not relevant_lines_start or relevant_lines_start == -1: if not relevant_lines_start or relevant_lines_start == -1:
if get_settings().config.verbosity_level >= 2: get_logger().warning(
get_logger().exception(
f"Failed to publish code suggestion, relevant_lines_start is {relevant_lines_start}" f"Failed to publish code suggestion, relevant_lines_start is {relevant_lines_start}"
) )
continue continue
if relevant_lines_end < relevant_lines_start: if relevant_lines_end < relevant_lines_start:
if get_settings().config.verbosity_level >= 2: get_logger().warning(
get_logger().exception(
f"Failed to publish code suggestion, " f"Failed to publish code suggestion, "
f"relevant_lines_end is {relevant_lines_end} and " f"relevant_lines_end is {relevant_lines_end} and "
f"relevant_lines_start is {relevant_lines_start}" f"relevant_lines_start is {relevant_lines_start}"
@ -159,7 +177,7 @@ class BitbucketServerProvider(GitProvider):
head_sha = self.pr.fromRef['latestCommit'] head_sha = self.pr.fromRef['latestCommit']
# if Bitbucket api version is >= 8.16 then use the merge-base api for 2-way diff calculation # if Bitbucket api version is >= 8.16 then use the merge-base api for 2-way diff calculation
if self.bitbucket_api_version is not None and self.bitbucket_api_version >= LooseVersion("8.16"): if self.bitbucket_api_version is not None and self.bitbucket_api_version >= parse_version("8.16"):
try: try:
base_sha = self.bitbucket_client.get(self._get_merge_base())['id'] base_sha = self.bitbucket_client.get(self._get_merge_base())['id']
except Exception as e: except Exception as e:
@ -174,7 +192,7 @@ class BitbucketServerProvider(GitProvider):
# if Bitbucket api version is None or < 7.0 then do a simple diff with a guaranteed common ancestor # if Bitbucket api version is None or < 7.0 then do a simple diff with a guaranteed common ancestor
base_sha = source_commits_list[-1]['parents'][0]['id'] base_sha = source_commits_list[-1]['parents'][0]['id']
# if Bitbucket api version is 7.0-8.15 then use 2-way diff functionality for the base_sha # if Bitbucket api version is 7.0-8.15 then use 2-way diff functionality for the base_sha
if self.bitbucket_api_version is not None and self.bitbucket_api_version >= LooseVersion("7.0"): if self.bitbucket_api_version is not None and self.bitbucket_api_version >= parse_version("7.0"):
try: try:
destination_commits = list( destination_commits = list(
self.bitbucket_client.get_commits(self.workspace_slug, self.repo_slug, base_sha, self.bitbucket_client.get_commits(self.workspace_slug, self.repo_slug, base_sha,
@ -200,27 +218,23 @@ class BitbucketServerProvider(GitProvider):
case 'ADD': case 'ADD':
edit_type = EDIT_TYPE.ADDED edit_type = EDIT_TYPE.ADDED
new_file_content_str = self.get_file(file_path, head_sha) new_file_content_str = self.get_file(file_path, head_sha)
if isinstance(new_file_content_str, (bytes, bytearray)): new_file_content_str = decode_if_bytes(new_file_content_str)
new_file_content_str = new_file_content_str.decode("utf-8")
original_file_content_str = "" original_file_content_str = ""
case 'DELETE': case 'DELETE':
edit_type = EDIT_TYPE.DELETED edit_type = EDIT_TYPE.DELETED
new_file_content_str = "" new_file_content_str = ""
original_file_content_str = self.get_file(file_path, base_sha) original_file_content_str = self.get_file(file_path, base_sha)
if isinstance(original_file_content_str, (bytes, bytearray)): original_file_content_str = decode_if_bytes(original_file_content_str)
original_file_content_str = original_file_content_str.decode("utf-8")
case 'RENAME': case 'RENAME':
edit_type = EDIT_TYPE.RENAMED edit_type = EDIT_TYPE.RENAMED
case _: case _:
edit_type = EDIT_TYPE.MODIFIED edit_type = EDIT_TYPE.MODIFIED
original_file_content_str = self.get_file(file_path, base_sha) original_file_content_str = self.get_file(file_path, base_sha)
if isinstance(original_file_content_str, (bytes, bytearray)): original_file_content_str = decode_if_bytes(original_file_content_str)
original_file_content_str = original_file_content_str.decode("utf-8")
new_file_content_str = self.get_file(file_path, head_sha) new_file_content_str = self.get_file(file_path, head_sha)
if isinstance(new_file_content_str, (bytes, bytearray)): new_file_content_str = decode_if_bytes(new_file_content_str)
new_file_content_str = new_file_content_str.decode("utf-8")
patch = load_large_diff(file_path, new_file_content_str, original_file_content_str) patch = load_large_diff(file_path, new_file_content_str, original_file_content_str, show_warning=False)
diff_files.append( diff_files.append(
FilePatchInfo( FilePatchInfo(
@ -388,10 +402,21 @@ class BitbucketServerProvider(GitProvider):
try: try:
projects_index = path_parts.index("projects") projects_index = path_parts.index("projects")
except ValueError as e: except ValueError:
projects_index = -1
try:
users_index = path_parts.index("users")
except ValueError:
users_index = -1
if projects_index == -1 and users_index == -1:
raise ValueError(f"The provided URL '{pr_url}' does not appear to be a Bitbucket PR URL") raise ValueError(f"The provided URL '{pr_url}' does not appear to be a Bitbucket PR URL")
if projects_index != -1:
path_parts = path_parts[projects_index:] path_parts = path_parts[projects_index:]
else:
path_parts = path_parts[users_index:]
if len(path_parts) < 6 or path_parts[2] != "repos" or path_parts[4] != "pull-requests": if len(path_parts) < 6 or path_parts[2] != "repos" or path_parts[4] != "pull-requests":
raise ValueError( raise ValueError(
@ -399,6 +424,8 @@ class BitbucketServerProvider(GitProvider):
) )
workspace_slug = path_parts[1] workspace_slug = path_parts[1]
if users_index != -1:
workspace_slug = f"~{workspace_slug}"
repo_slug = path_parts[3] repo_slug = path_parts[3]
try: try:
pr_number = int(path_parts[5]) pr_number = int(path_parts[5])

View File

@ -4,13 +4,15 @@ from collections import Counter
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
from urllib.parse import urlparse 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.algo.types import EDIT_TYPE, FilePatchInfo
from pr_agent.git_providers.codecommit_client import CodeCommitClient
from ..algo.utils import load_large_diff from ..algo.utils import load_large_diff
from .git_provider import GitProvider
from ..config_loader import get_settings from ..config_loader import get_settings
from ..log import get_logger from ..log import get_logger
from pr_agent.algo.language_handler import is_valid_file from .git_provider import GitProvider
class PullRequestCCMimic: class PullRequestCCMimic:
""" """

View File

@ -12,9 +12,9 @@ import requests
import urllib3.util import urllib3.util
from git import Repo from git import Repo
from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo
from pr_agent.config_loader import get_settings from pr_agent.config_loader import get_settings
from pr_agent.git_providers.git_provider import GitProvider from pr_agent.git_providers.git_provider import GitProvider
from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo
from pr_agent.git_providers.local_git_provider import PullRequestMimic from pr_agent.git_providers.local_git_provider import PullRequestMimic
from pr_agent.log import get_logger from pr_agent.log import get_logger

View File

@ -1,12 +1,12 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
# enum EDIT_TYPE (ADDED, DELETED, MODIFIED, RENAMED) # enum EDIT_TYPE (ADDED, DELETED, MODIFIED, RENAMED)
from typing import Optional from typing import Optional
from pr_agent.algo.types import FilePatchInfo
from pr_agent.algo.utils import Range, process_description from pr_agent.algo.utils import Range, process_description
from pr_agent.config_loader import get_settings from pr_agent.config_loader import get_settings
from pr_agent.algo.types import FilePatchInfo
from pr_agent.log import get_logger from pr_agent.log import get_logger
MAX_FILES_ALLOWED_FULL = 50 MAX_FILES_ALLOWED_FULL = 50
class GitProvider(ABC): class GitProvider(ABC):
@ -62,8 +62,8 @@ class GitProvider(ABC):
pass pass
def get_pr_description(self, full: bool = True, split_changes_walkthrough=False) -> str or tuple: 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.algo.utils import clip_tokens
from pr_agent.config_loader import get_settings
max_tokens_description = get_settings().get("CONFIG.MAX_DESCRIPTION_TOKENS", None) max_tokens_description = get_settings().get("CONFIG.MAX_DESCRIPTION_TOKENS", None)
description = self.get_pr_description_full() if full else self.get_user_description() description = self.get_pr_description_full() if full else self.get_user_description()
if split_changes_walkthrough: if split_changes_walkthrough:

View File

@ -1,22 +1,31 @@
import itertools import copy
import time import difflib
import hashlib import hashlib
import itertools
import re
import time
import traceback import traceback
import json
from datetime import datetime from datetime import datetime
from typing import Optional, Tuple from typing import Optional, Tuple
from urllib.parse import urlparse from urllib.parse import urlparse
from github import AppAuthentication, Auth, Github
from github import AppAuthentication, Auth, Github, GithubException
from retry import retry from retry import retry
from starlette_context import context from starlette_context import context
from ..algo.file_filter import filter_ignored from ..algo.file_filter import filter_ignored
from ..algo.git_patch_processing import extract_hunk_headers
from ..algo.language_handler import is_valid_file from ..algo.language_handler import is_valid_file
from ..algo.types import EDIT_TYPE 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, set_file_languages)
from ..config_loader import get_settings from ..config_loader import get_settings
from ..log import get_logger from ..log import get_logger
from ..servers.utils import RateLimitExceeded 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): class GithubProvider(GitProvider):
@ -166,6 +175,24 @@ class GithubProvider(GitProvider):
diff_files = [] diff_files = []
invalid_files_names = [] invalid_files_names = []
is_close_to_rate_limit = False
# The base.sha will point to the current state of the base branch (including parallel merges), not the original base commit when the PR was created
# We can fix this by finding the merge base commit between the PR head and base branches
# Note that The pr.head.sha is actually correct as is - it points to the latest commit in your PR branch.
# This SHA isn't affected by parallel merges to the base branch since it's specific to your PR's branch.
repo = self.repo_obj
pr = self.pr
try:
compare = repo.compare(pr.base.sha, pr.head.sha) # communication with GitHub
merge_base_commit = compare.merge_base_commit
except Exception as e:
get_logger().error(f"Failed to get merge base commit: {e}")
merge_base_commit = pr.base
if merge_base_commit.sha != pr.base.sha:
get_logger().info(
f"Using merge base commit {merge_base_commit.sha} instead of base commit ")
counter_valid = 0 counter_valid = 0
for file in files: for file in files:
if not is_valid_file(file.filename): if not is_valid_file(file.filename):
@ -173,7 +200,10 @@ class GithubProvider(GitProvider):
continue continue
patch = file.patch patch = file.patch
if is_close_to_rate_limit:
new_file_content_str = ""
original_file_content_str = ""
else:
# allow only a limited number of files to be fully loaded. We can manage the rest with diffs only # allow only a limited number of files to be fully loaded. We can manage the rest with diffs only
counter_valid += 1 counter_valid += 1
avoid_load = False avoid_load = False
@ -195,10 +225,12 @@ class GithubProvider(GitProvider):
if avoid_load: if avoid_load:
original_file_content_str = "" original_file_content_str = ""
else: else:
original_file_content_str = self._get_pr_file_content(file, self.pr.base.sha) original_file_content_str = self._get_pr_file_content(file, merge_base_commit.sha)
# original_file_content_str = self._get_pr_file_content(file, self.pr.base.sha)
if not patch: if not patch:
patch = load_large_diff(file.filename, new_file_content_str, original_file_content_str) patch = load_large_diff(file.filename, new_file_content_str, original_file_content_str)
if file.status == 'added': if file.status == 'added':
edit_type = EDIT_TYPE.ADDED edit_type = EDIT_TYPE.ADDED
elif file.status == 'removed': elif file.status == 'removed':
@ -212,9 +244,14 @@ class GithubProvider(GitProvider):
edit_type = EDIT_TYPE.UNKNOWN edit_type = EDIT_TYPE.UNKNOWN
# count number of lines added and removed # count number of lines added and removed
if hasattr(file, 'additions') and hasattr(file, 'deletions'):
num_plus_lines = file.additions
num_minus_lines = file.deletions
else:
patch_lines = patch.splitlines(keepends=True) patch_lines = patch.splitlines(keepends=True)
num_plus_lines = len([line for line in patch_lines if line.startswith('+')]) num_plus_lines = len([line for line in patch_lines if line.startswith('+')])
num_minus_lines = len([line for line in patch_lines if line.startswith('-')]) num_minus_lines = len([line for line in patch_lines if line.startswith('-')])
file_patch_canonical_structure = FilePatchInfo(original_file_content_str, new_file_content_str, patch, file_patch_canonical_structure = FilePatchInfo(original_file_content_str, new_file_content_str, patch,
file.filename, edit_type=edit_type, file.filename, edit_type=edit_type,
num_plus_lines=num_plus_lines, num_plus_lines=num_plus_lines,
@ -279,7 +316,6 @@ class GithubProvider(GitProvider):
relevant_line_in_file, relevant_line_in_file,
absolute_position) absolute_position)
if position == -1: if position == -1:
if get_settings().config.verbosity_level >= 2:
get_logger().info(f"Could not find position for {relevant_file} {relevant_line_in_file}") get_logger().info(f"Could not find position for {relevant_file} {relevant_line_in_file}")
subject_type = "FILE" subject_type = "FILE"
else: else:
@ -292,11 +328,9 @@ class GithubProvider(GitProvider):
# publish all comments in a single message # publish all comments in a single message
self.pr.create_review(commit=self.last_commit_id, comments=comments) self.pr.create_review(commit=self.last_commit_id, comments=comments)
except Exception as e: except Exception as e:
if get_settings().config.verbosity_level >= 2: get_logger().info(f"Initially failed to publish inline comments as committable")
get_logger().error(f"Failed to publish inline comments")
if (getattr(e, "status", None) == 422 if (getattr(e, "status", None) == 422 and not disable_fallback):
and get_settings().github.publish_inline_comments_fallback_with_verification and not disable_fallback):
pass # continue to try _publish_inline_comments_fallback_with_verification pass # continue to try _publish_inline_comments_fallback_with_verification
else: else:
raise e # will end up with publishing the comments one by one raise e # will end up with publishing the comments one by one
@ -304,7 +338,6 @@ class GithubProvider(GitProvider):
try: try:
self._publish_inline_comments_fallback_with_verification(comments) self._publish_inline_comments_fallback_with_verification(comments)
except Exception as e: except Exception as e:
if get_settings().config.verbosity_level >= 2:
get_logger().error(f"Failed to publish inline code comments fallback, error: {e}") get_logger().error(f"Failed to publish inline code comments fallback, error: {e}")
raise e raise e
@ -330,10 +363,8 @@ class GithubProvider(GitProvider):
for comment in fixed_comments_as_one_liner: for comment in fixed_comments_as_one_liner:
try: try:
self.publish_inline_comments([comment], disable_fallback=True) self.publish_inline_comments([comment], disable_fallback=True)
if get_settings().config.verbosity_level >= 2:
get_logger().info(f"Published invalid comment as a single line comment: {comment}") get_logger().info(f"Published invalid comment as a single line comment: {comment}")
except: except:
if get_settings().config.verbosity_level >= 2:
get_logger().error(f"Failed to publish invalid comment as a single line comment: {comment}") get_logger().error(f"Failed to publish invalid comment as a single line comment: {comment}")
def _verify_code_comment(self, comment: dict): def _verify_code_comment(self, comment: dict):
@ -392,7 +423,6 @@ class GithubProvider(GitProvider):
if fixed_comment != comment: if fixed_comment != comment:
fixed_comments.append(fixed_comment) fixed_comments.append(fixed_comment)
except Exception as e: except Exception as e:
if get_settings().config.verbosity_level >= 2:
get_logger().error(f"Failed to fix inline comment, error: {e}") get_logger().error(f"Failed to fix inline comment, error: {e}")
return fixed_comments return fixed_comments
@ -401,20 +431,21 @@ class GithubProvider(GitProvider):
Publishes code suggestions as comments on the PR. Publishes code suggestions as comments on the PR.
""" """
post_parameters_list = [] post_parameters_list = []
for suggestion in code_suggestions:
code_suggestions_validated = self.validate_comments_inside_hunks(code_suggestions)
for suggestion in code_suggestions_validated:
body = suggestion['body'] body = suggestion['body']
relevant_file = suggestion['relevant_file'] relevant_file = suggestion['relevant_file']
relevant_lines_start = suggestion['relevant_lines_start'] relevant_lines_start = suggestion['relevant_lines_start']
relevant_lines_end = suggestion['relevant_lines_end'] relevant_lines_end = suggestion['relevant_lines_end']
if not relevant_lines_start or relevant_lines_start == -1: if not relevant_lines_start or relevant_lines_start == -1:
if get_settings().config.verbosity_level >= 2:
get_logger().exception( get_logger().exception(
f"Failed to publish code suggestion, relevant_lines_start is {relevant_lines_start}") f"Failed to publish code suggestion, relevant_lines_start is {relevant_lines_start}")
continue continue
if relevant_lines_end < relevant_lines_start: if relevant_lines_end < relevant_lines_start:
if get_settings().config.verbosity_level >= 2:
get_logger().exception(f"Failed to publish code suggestion, " get_logger().exception(f"Failed to publish code suggestion, "
f"relevant_lines_end is {relevant_lines_end} and " f"relevant_lines_end is {relevant_lines_end} and "
f"relevant_lines_start is {relevant_lines_start}") f"relevant_lines_start is {relevant_lines_start}")
@ -441,13 +472,21 @@ class GithubProvider(GitProvider):
self.publish_inline_comments(post_parameters_list) self.publish_inline_comments(post_parameters_list)
return True return True
except Exception as e: except Exception as e:
if get_settings().config.verbosity_level >= 2:
get_logger().error(f"Failed to publish code suggestion, error: {e}") get_logger().error(f"Failed to publish code suggestion, error: {e}")
return False return False
def edit_comment(self, comment, body: str): def edit_comment(self, comment, body: str):
try:
body = self.limit_output_characters(body, self.max_comment_chars) body = self.limit_output_characters(body, self.max_comment_chars)
comment.edit(body=body) comment.edit(body=body)
except GithubException as e:
if hasattr(e, "status") and e.status == 403:
# Log as warning for permission-related issues (usually due to polling)
get_logger().warning(
"Failed to edit github comment due to permission restrictions",
artifact={"error": e})
else:
get_logger().exception(f"Failed to edit github comment", artifact={"error": e})
def edit_comment_from_comment_id(self, comment_id: int, body: str): def edit_comment_from_comment_id(self, comment_id: int, body: str):
try: try:
@ -501,6 +540,7 @@ class GithubProvider(GitProvider):
elif self.deployment_type == 'user': elif self.deployment_type == 'user':
same_comment_creator = self.github_user_id == existing_comment['user']['login'] same_comment_creator = self.github_user_id == existing_comment['user']['login']
if existing_comment['subject_type'] == 'file' and comment['path'] == existing_comment['path'] and same_comment_creator: if existing_comment['subject_type'] == 'file' and comment['path'] == existing_comment['path'] and same_comment_creator:
headers, data_patch = self.pr._requester.requestJsonAndCheck( headers, data_patch = self.pr._requester.requestJsonAndCheck(
"PATCH", f"{self.base_url}/repos/{self.repo}/pulls/comments/{existing_comment['id']}", input={"body":comment['body']} "PATCH", f"{self.base_url}/repos/{self.repo}/pulls/comments/{existing_comment['id']}", input={"body":comment['body']}
) )
@ -512,7 +552,6 @@ class GithubProvider(GitProvider):
) )
return True return True
except Exception as e: except Exception as e:
if get_settings().config.verbosity_level >= 2:
get_logger().error(f"Failed to publish diffview file summary, error: {e}") get_logger().error(f"Failed to publish diffview file summary, error: {e}")
return False return False
@ -801,7 +840,6 @@ class GithubProvider(GitProvider):
link = f"{self.base_url_html}/{self.repo}/pull/{self.pr_num}/files#diff-{sha_file}R{absolute_position}" link = f"{self.base_url_html}/{self.repo}/pull/{self.pr_num}/files#diff-{sha_file}R{absolute_position}"
return link return link
except Exception as e: except Exception as e:
if get_settings().config.verbosity_level >= 2:
get_logger().info(f"Failed adding line link, error: {e}") get_logger().info(f"Failed adding line link, error: {e}")
return "" return ""
@ -850,6 +888,84 @@ class GithubProvider(GitProvider):
except: except:
return "" return ""
def fetch_sub_issues(self, issue_url):
"""
Fetch sub-issues linked to the given GitHub issue URL using GraphQL via PyGitHub.
"""
sub_issues = set()
# Extract owner, repo, and issue number from URL
parts = issue_url.rstrip("/").split("/")
owner, repo, issue_number = parts[-4], parts[-3], parts[-1]
try:
# Gets Issue ID from Issue Number
query = f"""
query {{
repository(owner: "{owner}", name: "{repo}") {{
issue(number: {issue_number}) {{
id
}}
}}
}}
"""
response_tuple = self.github_client._Github__requester.requestJson("POST", "/graphql",
input={"query": query})
# Extract the JSON response from the tuple and parses it
if isinstance(response_tuple, tuple) and len(response_tuple) == 3:
response_json = json.loads(response_tuple[2])
else:
get_logger().error(f"Unexpected response format: {response_tuple}")
return sub_issues
issue_id = response_json.get("data", {}).get("repository", {}).get("issue", {}).get("id")
if not issue_id:
get_logger().warning(f"Issue ID not found for {issue_url}")
return sub_issues
# Fetch Sub-Issues
sub_issues_query = f"""
query {{
node(id: "{issue_id}") {{
... on Issue {{
subIssues(first: 10) {{
nodes {{
url
}}
}}
}}
}}
}}
"""
sub_issues_response_tuple = self.github_client._Github__requester.requestJson("POST", "/graphql", input={
"query": sub_issues_query})
# Extract the JSON response from the tuple and parses it
if isinstance(sub_issues_response_tuple, tuple) and len(sub_issues_response_tuple) == 3:
sub_issues_response_json = json.loads(sub_issues_response_tuple[2])
else:
get_logger().error("Unexpected sub-issues response format", artifact={"response": sub_issues_response_tuple})
return sub_issues
if not sub_issues_response_json.get("data", {}).get("node", {}).get("subIssues"):
get_logger().error("Invalid sub-issues response structure")
return sub_issues
nodes = sub_issues_response_json.get("data", {}).get("node", {}).get("subIssues", {}).get("nodes", [])
get_logger().info(f"Github Sub-issues fetched: {len(nodes)}", artifact={"nodes": nodes})
for sub_issue in nodes:
if "url" in sub_issue:
sub_issues.add(sub_issue["url"])
except Exception as e:
get_logger().exception(f"Failed to fetch sub-issues. Error: {e}")
return sub_issues
def auto_approve(self) -> bool: def auto_approve(self) -> bool:
try: try:
res = self.pr.create_review(event="APPROVE") res = self.pr.create_review(event="APPROVE")
@ -862,3 +978,89 @@ class GithubProvider(GitProvider):
def calc_pr_statistics(self, pull_request_data: dict): def calc_pr_statistics(self, pull_request_data: dict):
return {} return {}
def validate_comments_inside_hunks(self, code_suggestions):
"""
validate that all committable comments are inside PR hunks - this is a must for committable comments in GitHub
"""
code_suggestions_copy = copy.deepcopy(code_suggestions)
diff_files = self.get_diff_files()
RE_HUNK_HEADER = re.compile(
r"^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@[ ]?(.*)")
diff_files = set_file_languages(diff_files)
for suggestion in code_suggestions_copy:
try:
relevant_file_path = suggestion['relevant_file']
for file in diff_files:
if file.filename == relevant_file_path:
# generate on-demand the patches range for the relevant file
patch_str = file.patch
if not hasattr(file, 'patches_range'):
file.patches_range = []
patch_lines = patch_str.splitlines()
for i, line in enumerate(patch_lines):
if line.startswith('@@'):
match = RE_HUNK_HEADER.match(line)
# identify hunk header
if match:
section_header, size1, size2, start1, start2 = extract_hunk_headers(match)
file.patches_range.append({'start': start2, 'end': start2 + size2 - 1})
patches_range = file.patches_range
comment_start_line = suggestion.get('relevant_lines_start', None)
comment_end_line = suggestion.get('relevant_lines_end', None)
original_suggestion = suggestion.get('original_suggestion', None) # needed for diff code
if not comment_start_line or not comment_end_line or not original_suggestion:
continue
# check if the comment is inside a valid hunk
is_valid_hunk = False
min_distance = float('inf')
patch_range_min = None
# find the hunk that contains the comment, or the closest one
for i, patch_range in enumerate(patches_range):
d1 = comment_start_line - patch_range['start']
d2 = patch_range['end'] - comment_end_line
if d1 >= 0 and d2 >= 0: # found a valid hunk
is_valid_hunk = True
min_distance = 0
patch_range_min = patch_range
break
elif d1 * d2 <= 0: # comment is possibly inside the hunk
d1_clip = abs(min(0, d1))
d2_clip = abs(min(0, d2))
d = max(d1_clip, d2_clip)
if d < min_distance:
patch_range_min = patch_range
min_distance = min(min_distance, d)
if not is_valid_hunk:
if min_distance < 10: # 10 lines - a reasonable distance to consider the comment inside the hunk
# make the suggestion non-committable, yet multi line
suggestion['relevant_lines_start'] = max(suggestion['relevant_lines_start'], patch_range_min['start'])
suggestion['relevant_lines_end'] = min(suggestion['relevant_lines_end'], patch_range_min['end'])
body = suggestion['body'].strip()
# present new diff code in collapsible
existing_code = original_suggestion['existing_code'].rstrip() + "\n"
improved_code = original_suggestion['improved_code'].rstrip() + "\n"
diff = difflib.unified_diff(existing_code.split('\n'),
improved_code.split('\n'), n=999)
patch_orig = "\n".join(diff)
patch = "\n".join(patch_orig.splitlines()[5:]).strip('\n')
diff_code = f"\n\n<details><summary>New proposed code:</summary>\n\n```diff\n{patch.rstrip()}\n```"
# replace ```suggestion ... ``` with diff_code, using regex:
body = re.sub(r'```suggestion.*?```', diff_code, body, flags=re.DOTALL)
body += "\n\n</details>"
suggestion['body'] = body
get_logger().info(f"Comment was moved to a valid hunk, "
f"start_line={suggestion['relevant_lines_start']}, end_line={suggestion['relevant_lines_end']}, file={file.filename}")
else:
get_logger().error(f"Comment is not inside a valid hunk, "
f"start_line={suggestion['relevant_lines_start']}, end_line={suggestion['relevant_lines_end']}, file={file.filename}")
except Exception as e:
get_logger().error(f"Failed to process patch for committable comment, error: {e}")
return code_suggestions_copy

View File

@ -1,3 +1,4 @@
import difflib
import hashlib import hashlib
import re import re
from typing import Optional, Tuple from typing import Optional, Tuple
@ -7,13 +8,16 @@ import gitlab
import requests import requests
from gitlab import GitlabGetError from gitlab import GitlabGetError
from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo
from ..algo.file_filter import filter_ignored from ..algo.file_filter import filter_ignored
from ..algo.language_handler import is_valid_file 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 ..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 ..log import get_logger
from .git_provider import MAX_FILES_ALLOWED_FULL, GitProvider
class DiffNotFoundError(Exception): class DiffNotFoundError(Exception):
@ -177,7 +181,13 @@ class GitLabProvider(GitProvider):
get_logger().exception(f"Could not update merge request {self.id_mr} description: {e}") get_logger().exception(f"Could not update merge request {self.id_mr} description: {e}")
def get_latest_commit_url(self): def get_latest_commit_url(self):
try:
return self.mr.commits().next().web_url return self.mr.commits().next().web_url
except StopIteration: # no commits
return ""
except Exception as e:
get_logger().exception(f"Could not get latest commit URL: {e}")
return ""
def get_comment_url(self, comment): def get_comment_url(self, comment):
return f"{self.mr.web_url}#note_{comment.id}" return f"{self.mr.web_url}#note_{comment.id}"
@ -190,6 +200,9 @@ class GitLabProvider(GitProvider):
self.publish_persistent_comment_full(pr_comment, initial_header, update_header, name, final_update_message) self.publish_persistent_comment_full(pr_comment, initial_header, update_header, name, final_update_message)
def publish_comment(self, mr_comment: str, is_temporary: bool = False): def publish_comment(self, mr_comment: str, is_temporary: bool = False):
if is_temporary and not get_settings().config.publish_output_progress:
get_logger().debug(f"Skipping publish_comment for temporary comment: {mr_comment}")
return None
mr_comment = self.limit_output_characters(mr_comment, self.max_comment_chars) mr_comment = self.limit_output_characters(mr_comment, self.max_comment_chars)
comment = self.mr.notes.create({'body': mr_comment}) comment = self.mr.notes.create({'body': mr_comment})
if is_temporary: if is_temporary:
@ -275,20 +288,23 @@ class GitLabProvider(GitProvider):
new_code_snippet = original_suggestion['improved_code'] new_code_snippet = original_suggestion['improved_code']
content = original_suggestion['suggestion_content'] content = original_suggestion['suggestion_content']
label = original_suggestion['label'] label = original_suggestion['label']
if 'score' in original_suggestion: score = original_suggestion.get('score', 7)
score = original_suggestion['score']
else:
score = 7
if hasattr(self, 'main_language'): if hasattr(self, 'main_language'):
language = self.main_language language = self.main_language
else: else:
language = '' language = ''
link = self.get_line_link(relevant_file, line_start, line_end) link = self.get_line_link(relevant_file, line_start, line_end)
body_fallback =f"**Suggestion:** {content} [{label}, importance: {score}]\n___\n" body_fallback =f"**Suggestion:** {content} [{label}, importance: {score}]\n\n"
body_fallback +=f"\n\nReplace lines ([{line_start}-{line_end}]({link}))\n\n```{language}\n{old_code_snippet}\n````\n\n" body_fallback +=f"\n\n<details><summary>[{target_file.filename} [{line_start}-{line_end}]]({link}):</summary>\n\n"
body_fallback +=f"with\n\n```{language}\n{new_code_snippet}\n````" body_fallback += f"\n\n___\n\n`(Cannot implement directly - GitLab API allows committable suggestions strictly on MR diff lines)`"
body_fallback += f"\n\n___\n\n`(Cannot implement this suggestion directly, as gitlab API does not enable committing to a non -+ line in a PR)`" body_fallback+="</details>\n\n"
diff_patch = difflib.unified_diff(old_code_snippet.split('\n'),
new_code_snippet.split('\n'), n=999)
patch_orig = "\n".join(diff_patch)
patch = "\n".join(patch_orig.splitlines()[5:]).strip('\n')
diff_code = f"\n\n```diff\n{patch.rstrip()}\n```"
body_fallback += diff_code
# Create a general note on the file in the MR # Create a general note on the file in the MR
self.mr.notes.create({ self.mr.notes.create({
@ -301,6 +317,7 @@ class GitLabProvider(GitProvider):
'file_path': f'{target_file.filename}', 'file_path': f'{target_file.filename}',
} }
}) })
get_logger().debug(f"Created fallback comment in MR {self.id_mr} with position {pos_obj}")
# get_logger().debug( # get_logger().debug(
# f"Failed to create comment in MR {self.id_mr} with position {pos_obj} (probably not a '+' line)") # f"Failed to create comment in MR {self.id_mr} with position {pos_obj} (probably not a '+' line)")

View File

@ -4,9 +4,9 @@ from typing import List
from git import Repo 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.config_loader import _find_repository_root, get_settings
from pr_agent.git_providers.git_provider import GitProvider from pr_agent.git_providers.git_provider import GitProvider
from pr_agent.algo.types import EDIT_TYPE, FilePatchInfo
from pr_agent.log import get_logger from pr_agent.log import get_logger
@ -141,6 +141,18 @@ class LocalGitProvider(GitProvider):
def remove_comment(self, comment): def remove_comment(self, comment):
pass # Not applicable to the local git provider, but required by the interface pass # Not applicable to the local git provider, but required by the interface
def add_eyes_reaction(self, comment):
pass # Not applicable to the local git provider, but required by the interface
def get_commit_messages(self):
pass # Not applicable to the local git provider, but required by the interface
def get_repo_settings(self):
pass # Not applicable to the local git provider, but required by the interface
def remove_reaction(self, comment):
pass # Not applicable to the local git provider, but required by the interface
def get_languages(self): def get_languages(self):
""" """
Calculate percentage of languages in repository. Used for hunk prioritisation. Calculate percentage of languages in repository. Used for hunk prioritisation.

View File

@ -3,11 +3,12 @@ import os
import tempfile import tempfile
from dynaconf import Dynaconf from dynaconf import Dynaconf
from starlette_context import context
from pr_agent.config_loader import get_settings from pr_agent.config_loader import get_settings
from pr_agent.git_providers import get_git_provider, 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 pr_agent.log import get_logger
from starlette_context import context
def apply_repo_settings(pr_url): def apply_repo_settings(pr_url):
@ -98,5 +99,5 @@ def set_claude_model():
""" """
model_claude = "bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0" model_claude = "bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0"
get_settings().set('config.model', model_claude) get_settings().set('config.model', model_claude)
get_settings().set('config.model_turbo', model_claude) get_settings().set('config.model_weak', model_claude)
get_settings().set('config.fallback_models', [model_claude]) get_settings().set('config.fallback_models', [model_claude])

View File

@ -1,5 +1,6 @@
from pr_agent.config_loader import get_settings 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 = { _IDENTITY_PROVIDERS = {
'default': DefaultIdentityProvider 'default': DefaultIdentityProvider

View File

@ -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): class DefaultIdentityProvider(IdentityProvider):

Some files were not shown because too many files have changed in this diff Show More