xai-review 0.29.0__tar.gz → 0.31.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of xai-review might be problematic. Click here for more details.

Files changed (387) hide show
  1. {xai_review-0.29.0/xai_review.egg-info → xai_review-0.31.0}/PKG-INFO +21 -12
  2. {xai_review-0.29.0 → xai_review-0.31.0}/README.md +20 -11
  3. xai_review-0.31.0/ai_review/clients/gitea/client.py +31 -0
  4. xai_review-0.31.0/ai_review/clients/gitea/pr/client.py +118 -0
  5. xai_review-0.31.0/ai_review/clients/gitea/pr/schema/comments.py +37 -0
  6. xai_review-0.31.0/ai_review/clients/gitea/pr/schema/files.py +16 -0
  7. xai_review-0.31.0/ai_review/clients/gitea/pr/schema/pull_request.py +18 -0
  8. xai_review-0.31.0/ai_review/clients/gitea/pr/schema/user.py +6 -0
  9. xai_review-0.31.0/ai_review/clients/gitea/pr/types.py +25 -0
  10. xai_review-0.31.0/ai_review/clients/gitea/tools.py +6 -0
  11. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/review.py +1 -0
  12. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/vcs/base.py +8 -1
  13. xai_review-0.31.0/ai_review/libs/config/vcs/gitea.py +13 -0
  14. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/constants/vcs_provider.py +1 -0
  15. xai_review-0.31.0/ai_review/services/review/gateway/review_dry_run_comment_gateway.py +42 -0
  16. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/service.py +9 -3
  17. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/vcs/factory.py +3 -0
  18. xai_review-0.31.0/ai_review/services/vcs/gitea/adapter.py +22 -0
  19. xai_review-0.31.0/ai_review/services/vcs/gitea/client.py +151 -0
  20. xai_review-0.31.0/ai_review/tests/fixtures/clients/gitea.py +141 -0
  21. xai_review-0.29.0/ai_review/tests/fixtures/services/review/gateway/comment.py → xai_review-0.31.0/ai_review/tests/fixtures/services/review/gateway/review_comment_gateway.py +1 -1
  22. xai_review-0.31.0/ai_review/tests/fixtures/services/review/gateway/review_dry_run_comment_gateway.py +103 -0
  23. xai_review-0.31.0/ai_review/tests/fixtures/services/review/gateway/review_llm_gateway.py +34 -0
  24. xai_review-0.31.0/ai_review/tests/suites/clients/gitea/test_client.py +14 -0
  25. xai_review-0.31.0/ai_review/tests/suites/clients/gitea/test_tools.py +26 -0
  26. xai_review-0.29.0/ai_review/tests/suites/services/review/gateway/test_comment.py → xai_review-0.31.0/ai_review/tests/suites/services/review/gateway/test_review_comment_gateway.py +1 -1
  27. xai_review-0.31.0/ai_review/tests/suites/services/review/gateway/test_review_dry_run_comment_gateway.py +93 -0
  28. xai_review-0.29.0/ai_review/tests/suites/services/review/gateway/test_llm.py → xai_review-0.31.0/ai_review/tests/suites/services/review/gateway/test_review_llm_gateway.py +1 -15
  29. xai_review-0.31.0/ai_review/tests/suites/services/review/runner/__init__.py +0 -0
  30. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/runner/test_context.py +2 -2
  31. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/runner/test_inline.py +2 -2
  32. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/runner/test_inline_reply.py +2 -2
  33. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/runner/test_summary.py +2 -2
  34. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/runner/test_summary_reply.py +2 -2
  35. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/test_service.py +18 -0
  36. xai_review-0.31.0/ai_review/tests/suites/services/vcs/__init__.py +0 -0
  37. xai_review-0.31.0/ai_review/tests/suites/services/vcs/bitbucket/__init__.py +0 -0
  38. xai_review-0.31.0/ai_review/tests/suites/services/vcs/gitea/__init__.py +0 -0
  39. xai_review-0.31.0/ai_review/tests/suites/services/vcs/gitea/test_adapter.py +52 -0
  40. xai_review-0.31.0/ai_review/tests/suites/services/vcs/gitea/test_client.py +86 -0
  41. xai_review-0.31.0/ai_review/tests/suites/services/vcs/github/__init__.py +0 -0
  42. xai_review-0.31.0/ai_review/tests/suites/services/vcs/gitlab/__init__.py +0 -0
  43. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/vcs/test_factory.py +7 -0
  44. {xai_review-0.29.0 → xai_review-0.31.0}/pyproject.toml +1 -1
  45. {xai_review-0.29.0 → xai_review-0.31.0/xai_review.egg-info}/PKG-INFO +21 -12
  46. {xai_review-0.29.0 → xai_review-0.31.0}/xai_review.egg-info/SOURCES.txt +31 -6
  47. xai_review-0.29.0/ai_review/tests/fixtures/services/review/gateway/llm.py +0 -17
  48. {xai_review-0.29.0 → xai_review-0.31.0}/LICENSE +0 -0
  49. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/__init__.py +0 -0
  50. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/cli/__init__.py +0 -0
  51. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/cli/commands/__init__.py +0 -0
  52. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/cli/commands/run_context_review.py +0 -0
  53. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/cli/commands/run_inline_reply_review.py +0 -0
  54. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/cli/commands/run_inline_review.py +0 -0
  55. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/cli/commands/run_review.py +0 -0
  56. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/cli/commands/run_summary_reply_review.py +0 -0
  57. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/cli/commands/run_summary_review.py +0 -0
  58. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/cli/main.py +0 -0
  59. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/__init__.py +0 -0
  60. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/bitbucket/__init__.py +0 -0
  61. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/bitbucket/client.py +0 -0
  62. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/bitbucket/pr/__init__.py +0 -0
  63. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/bitbucket/pr/client.py +0 -0
  64. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/bitbucket/pr/schema/__init__.py +0 -0
  65. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/bitbucket/pr/schema/comments.py +0 -0
  66. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/bitbucket/pr/schema/files.py +0 -0
  67. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/bitbucket/pr/schema/pull_request.py +0 -0
  68. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/bitbucket/pr/schema/user.py +0 -0
  69. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/bitbucket/pr/types.py +0 -0
  70. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/bitbucket/tools.py +0 -0
  71. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/claude/__init__.py +0 -0
  72. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/claude/client.py +0 -0
  73. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/claude/schema.py +0 -0
  74. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/claude/types.py +0 -0
  75. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gemini/__init__.py +0 -0
  76. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gemini/client.py +0 -0
  77. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gemini/schema.py +0 -0
  78. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gemini/types.py +0 -0
  79. {xai_review-0.29.0/ai_review/clients/github → xai_review-0.31.0/ai_review/clients/gitea}/__init__.py +0 -0
  80. {xai_review-0.29.0/ai_review/clients/github → xai_review-0.31.0/ai_review/clients/gitea}/pr/__init__.py +0 -0
  81. {xai_review-0.29.0/ai_review/clients/github → xai_review-0.31.0/ai_review/clients/gitea}/pr/schema/__init__.py +0 -0
  82. {xai_review-0.29.0/ai_review/clients/gitlab → xai_review-0.31.0/ai_review/clients/github}/__init__.py +0 -0
  83. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/github/client.py +0 -0
  84. {xai_review-0.29.0/ai_review/clients/gitlab/mr → xai_review-0.31.0/ai_review/clients/github/pr}/__init__.py +0 -0
  85. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/github/pr/client.py +0 -0
  86. {xai_review-0.29.0/ai_review/clients/gitlab/mr → xai_review-0.31.0/ai_review/clients/github/pr}/schema/__init__.py +0 -0
  87. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/github/pr/schema/comments.py +0 -0
  88. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/github/pr/schema/files.py +0 -0
  89. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/github/pr/schema/pull_request.py +0 -0
  90. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/github/pr/schema/reviews.py +0 -0
  91. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/github/pr/schema/user.py +0 -0
  92. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/github/pr/types.py +0 -0
  93. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/github/tools.py +0 -0
  94. {xai_review-0.29.0/ai_review/clients/ollama → xai_review-0.31.0/ai_review/clients/gitlab}/__init__.py +0 -0
  95. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gitlab/client.py +0 -0
  96. {xai_review-0.29.0/ai_review/clients/openai → xai_review-0.31.0/ai_review/clients/gitlab/mr}/__init__.py +0 -0
  97. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gitlab/mr/client.py +0 -0
  98. {xai_review-0.29.0/ai_review/libs → xai_review-0.31.0/ai_review/clients/gitlab/mr/schema}/__init__.py +0 -0
  99. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gitlab/mr/schema/changes.py +0 -0
  100. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gitlab/mr/schema/discussions.py +0 -0
  101. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gitlab/mr/schema/notes.py +0 -0
  102. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gitlab/mr/schema/position.py +0 -0
  103. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gitlab/mr/schema/user.py +0 -0
  104. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gitlab/mr/types.py +0 -0
  105. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/gitlab/tools.py +0 -0
  106. {xai_review-0.29.0/ai_review/libs/asynchronous → xai_review-0.31.0/ai_review/clients/ollama}/__init__.py +0 -0
  107. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/ollama/client.py +0 -0
  108. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/ollama/schema.py +0 -0
  109. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/ollama/types.py +0 -0
  110. {xai_review-0.29.0/ai_review/libs/config → xai_review-0.31.0/ai_review/clients/openai}/__init__.py +0 -0
  111. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/openai/client.py +0 -0
  112. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/openai/schema.py +0 -0
  113. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/clients/openai/types.py +0 -0
  114. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/config.py +0 -0
  115. {xai_review-0.29.0/ai_review/libs/config/llm → xai_review-0.31.0/ai_review/libs}/__init__.py +0 -0
  116. {xai_review-0.29.0/ai_review/libs/config/vcs → xai_review-0.31.0/ai_review/libs/asynchronous}/__init__.py +0 -0
  117. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/asynchronous/gather.py +0 -0
  118. {xai_review-0.29.0/ai_review/libs/constants → xai_review-0.31.0/ai_review/libs/config}/__init__.py +0 -0
  119. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/artifacts.py +0 -0
  120. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/base.py +0 -0
  121. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/core.py +0 -0
  122. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/http.py +0 -0
  123. {xai_review-0.29.0/ai_review/libs/diff → xai_review-0.31.0/ai_review/libs/config/llm}/__init__.py +0 -0
  124. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/llm/base.py +0 -0
  125. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/llm/claude.py +0 -0
  126. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/llm/gemini.py +0 -0
  127. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/llm/meta.py +0 -0
  128. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/llm/ollama.py +0 -0
  129. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/llm/openai.py +0 -0
  130. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/logger.py +0 -0
  131. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/prompt.py +0 -0
  132. {xai_review-0.29.0/ai_review/libs/http → xai_review-0.31.0/ai_review/libs/config/vcs}/__init__.py +0 -0
  133. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/vcs/bitbucket.py +0 -0
  134. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/vcs/github.py +0 -0
  135. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/vcs/gitlab.py +0 -0
  136. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/config/vcs/pagination.py +0 -0
  137. {xai_review-0.29.0/ai_review/libs/http/event_hooks → xai_review-0.31.0/ai_review/libs/constants}/__init__.py +0 -0
  138. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/constants/llm_provider.py +0 -0
  139. {xai_review-0.29.0/ai_review/libs/http/transports → xai_review-0.31.0/ai_review/libs/diff}/__init__.py +0 -0
  140. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/diff/models.py +0 -0
  141. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/diff/parser.py +0 -0
  142. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/diff/tools.py +0 -0
  143. {xai_review-0.29.0/ai_review/libs/llm → xai_review-0.31.0/ai_review/libs/http}/__init__.py +0 -0
  144. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/http/client.py +0 -0
  145. {xai_review-0.29.0/ai_review/libs/template → xai_review-0.31.0/ai_review/libs/http/event_hooks}/__init__.py +0 -0
  146. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/http/event_hooks/base.py +0 -0
  147. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/http/event_hooks/logger.py +0 -0
  148. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/http/handlers.py +0 -0
  149. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/http/paginate.py +0 -0
  150. {xai_review-0.29.0/ai_review/prompts → xai_review-0.31.0/ai_review/libs/http/transports}/__init__.py +0 -0
  151. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/http/transports/retry.py +0 -0
  152. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/json.py +0 -0
  153. {xai_review-0.29.0/ai_review/resources → xai_review-0.31.0/ai_review/libs/llm}/__init__.py +0 -0
  154. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/llm/output_json_parser.py +0 -0
  155. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/logger.py +0 -0
  156. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/resources.py +0 -0
  157. {xai_review-0.29.0/ai_review/services → xai_review-0.31.0/ai_review/libs/template}/__init__.py +0 -0
  158. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/libs/template/render.py +0 -0
  159. {xai_review-0.29.0/ai_review/services/artifacts → xai_review-0.31.0/ai_review/prompts}/__init__.py +0 -0
  160. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/prompts/default_context.md +0 -0
  161. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/prompts/default_inline.md +0 -0
  162. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/prompts/default_inline_reply.md +0 -0
  163. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/prompts/default_summary.md +0 -0
  164. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/prompts/default_summary_reply.md +0 -0
  165. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/prompts/default_system_context.md +0 -0
  166. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/prompts/default_system_inline.md +0 -0
  167. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/prompts/default_system_inline_reply.md +0 -0
  168. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/prompts/default_system_summary.md +0 -0
  169. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/prompts/default_system_summary_reply.md +0 -0
  170. {xai_review-0.29.0/ai_review/services/cost → xai_review-0.31.0/ai_review/resources}/__init__.py +0 -0
  171. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/resources/pricing.yaml +0 -0
  172. {xai_review-0.29.0/ai_review/services/diff → xai_review-0.31.0/ai_review/services}/__init__.py +0 -0
  173. {xai_review-0.29.0/ai_review/services/git → xai_review-0.31.0/ai_review/services/artifacts}/__init__.py +0 -0
  174. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/artifacts/schema.py +0 -0
  175. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/artifacts/service.py +0 -0
  176. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/artifacts/tools.py +0 -0
  177. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/artifacts/types.py +0 -0
  178. {xai_review-0.29.0/ai_review/services/llm → xai_review-0.31.0/ai_review/services/cost}/__init__.py +0 -0
  179. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/cost/schema.py +0 -0
  180. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/cost/service.py +0 -0
  181. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/cost/types.py +0 -0
  182. {xai_review-0.29.0/ai_review/services/llm/claude → xai_review-0.31.0/ai_review/services/diff}/__init__.py +0 -0
  183. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/diff/renderers.py +0 -0
  184. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/diff/schema.py +0 -0
  185. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/diff/service.py +0 -0
  186. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/diff/tools.py +0 -0
  187. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/diff/types.py +0 -0
  188. {xai_review-0.29.0/ai_review/services/llm/gemini → xai_review-0.31.0/ai_review/services/git}/__init__.py +0 -0
  189. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/git/service.py +0 -0
  190. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/git/types.py +0 -0
  191. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/hook/__init__.py +0 -0
  192. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/hook/constants.py +0 -0
  193. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/hook/service.py +0 -0
  194. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/hook/types.py +0 -0
  195. {xai_review-0.29.0/ai_review/services/llm/ollama → xai_review-0.31.0/ai_review/services/llm}/__init__.py +0 -0
  196. {xai_review-0.29.0/ai_review/services/llm/openai → xai_review-0.31.0/ai_review/services/llm/claude}/__init__.py +0 -0
  197. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/llm/claude/client.py +0 -0
  198. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/llm/factory.py +0 -0
  199. {xai_review-0.29.0/ai_review/services/prompt → xai_review-0.31.0/ai_review/services/llm/gemini}/__init__.py +0 -0
  200. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/llm/gemini/client.py +0 -0
  201. {xai_review-0.29.0/ai_review/services/review → xai_review-0.31.0/ai_review/services/llm/ollama}/__init__.py +0 -0
  202. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/llm/ollama/client.py +0 -0
  203. {xai_review-0.29.0/ai_review/services/review/gateway → xai_review-0.31.0/ai_review/services/llm/openai}/__init__.py +0 -0
  204. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/llm/openai/client.py +0 -0
  205. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/llm/types.py +0 -0
  206. {xai_review-0.29.0/ai_review/services/review/internal → xai_review-0.31.0/ai_review/services/prompt}/__init__.py +0 -0
  207. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/prompt/adapter.py +0 -0
  208. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/prompt/schema.py +0 -0
  209. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/prompt/service.py +0 -0
  210. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/prompt/tools.py +0 -0
  211. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/prompt/types.py +0 -0
  212. {xai_review-0.29.0/ai_review/services/review/internal/inline → xai_review-0.31.0/ai_review/services/review}/__init__.py +0 -0
  213. {xai_review-0.29.0/ai_review/services/review/internal/inline_reply → xai_review-0.31.0/ai_review/services/review/gateway}/__init__.py +0 -0
  214. /xai_review-0.29.0/ai_review/services/review/gateway/comment.py → /xai_review-0.31.0/ai_review/services/review/gateway/review_comment_gateway.py +0 -0
  215. /xai_review-0.29.0/ai_review/services/review/gateway/llm.py → /xai_review-0.31.0/ai_review/services/review/gateway/review_llm_gateway.py +0 -0
  216. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/gateway/types.py +0 -0
  217. {xai_review-0.29.0/ai_review/services/review/internal/policy → xai_review-0.31.0/ai_review/services/review/internal}/__init__.py +0 -0
  218. {xai_review-0.29.0/ai_review/services/review/internal/summary → xai_review-0.31.0/ai_review/services/review/internal/inline}/__init__.py +0 -0
  219. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/inline/schema.py +0 -0
  220. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/inline/service.py +0 -0
  221. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/inline/types.py +0 -0
  222. {xai_review-0.29.0/ai_review/services/review/internal/summary_reply → xai_review-0.31.0/ai_review/services/review/internal/inline_reply}/__init__.py +0 -0
  223. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/inline_reply/schema.py +0 -0
  224. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/inline_reply/service.py +0 -0
  225. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/inline_reply/types.py +0 -0
  226. {xai_review-0.29.0/ai_review/services/review/runner → xai_review-0.31.0/ai_review/services/review/internal/policy}/__init__.py +0 -0
  227. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/policy/service.py +0 -0
  228. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/policy/types.py +0 -0
  229. {xai_review-0.29.0/ai_review/services/vcs → xai_review-0.31.0/ai_review/services/review/internal/summary}/__init__.py +0 -0
  230. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/summary/schema.py +0 -0
  231. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/summary/service.py +0 -0
  232. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/summary/types.py +0 -0
  233. {xai_review-0.29.0/ai_review/services/vcs/bitbucket → xai_review-0.31.0/ai_review/services/review/internal/summary_reply}/__init__.py +0 -0
  234. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/summary_reply/schema.py +0 -0
  235. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/summary_reply/service.py +0 -0
  236. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/internal/summary_reply/types.py +0 -0
  237. {xai_review-0.29.0/ai_review/services/vcs/github → xai_review-0.31.0/ai_review/services/review/runner}/__init__.py +0 -0
  238. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/runner/context.py +0 -0
  239. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/runner/inline.py +0 -0
  240. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/runner/inline_reply.py +0 -0
  241. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/runner/summary.py +0 -0
  242. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/runner/summary_reply.py +0 -0
  243. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/review/runner/types.py +0 -0
  244. {xai_review-0.29.0/ai_review/services/vcs/gitlab → xai_review-0.31.0/ai_review/services/vcs}/__init__.py +0 -0
  245. {xai_review-0.29.0/ai_review/tests → xai_review-0.31.0/ai_review/services/vcs/bitbucket}/__init__.py +0 -0
  246. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/vcs/bitbucket/adapter.py +0 -0
  247. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/vcs/bitbucket/client.py +0 -0
  248. {xai_review-0.29.0/ai_review/tests/fixtures → xai_review-0.31.0/ai_review/services/vcs/gitea}/__init__.py +0 -0
  249. {xai_review-0.29.0/ai_review/tests/fixtures/clients → xai_review-0.31.0/ai_review/services/vcs/github}/__init__.py +0 -0
  250. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/vcs/github/adapter.py +0 -0
  251. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/vcs/github/client.py +0 -0
  252. {xai_review-0.29.0/ai_review/tests/fixtures/libs → xai_review-0.31.0/ai_review/services/vcs/gitlab}/__init__.py +0 -0
  253. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/vcs/gitlab/adapter.py +0 -0
  254. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/vcs/gitlab/client.py +0 -0
  255. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/services/vcs/types.py +0 -0
  256. {xai_review-0.29.0/ai_review/tests/fixtures/libs/llm → xai_review-0.31.0/ai_review/tests}/__init__.py +0 -0
  257. {xai_review-0.29.0/ai_review/tests/fixtures/services → xai_review-0.31.0/ai_review/tests/fixtures}/__init__.py +0 -0
  258. {xai_review-0.29.0/ai_review/tests/fixtures/services/review → xai_review-0.31.0/ai_review/tests/fixtures/clients}/__init__.py +0 -0
  259. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/clients/bitbucket.py +0 -0
  260. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/clients/claude.py +0 -0
  261. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/clients/gemini.py +0 -0
  262. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/clients/github.py +0 -0
  263. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/clients/gitlab.py +0 -0
  264. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/clients/ollama.py +0 -0
  265. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/clients/openai.py +0 -0
  266. {xai_review-0.29.0/ai_review/tests/fixtures/services/review/gateway → xai_review-0.31.0/ai_review/tests/fixtures/libs}/__init__.py +0 -0
  267. {xai_review-0.29.0/ai_review/tests/fixtures/services/review/internal → xai_review-0.31.0/ai_review/tests/fixtures/libs/llm}/__init__.py +0 -0
  268. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/libs/llm/output_json_parser.py +0 -0
  269. {xai_review-0.29.0/ai_review/tests/fixtures/services/review/runner → xai_review-0.31.0/ai_review/tests/fixtures/services}/__init__.py +0 -0
  270. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/artifacts.py +0 -0
  271. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/cost.py +0 -0
  272. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/diff.py +0 -0
  273. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/git.py +0 -0
  274. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/hook.py +0 -0
  275. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/llm.py +0 -0
  276. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/prompt.py +0 -0
  277. {xai_review-0.29.0/ai_review/tests/suites → xai_review-0.31.0/ai_review/tests/fixtures/services/review}/__init__.py +0 -0
  278. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/review/base.py +0 -0
  279. {xai_review-0.29.0/ai_review/tests/suites/cli → xai_review-0.31.0/ai_review/tests/fixtures/services/review/gateway}/__init__.py +0 -0
  280. {xai_review-0.29.0/ai_review/tests/suites/clients → xai_review-0.31.0/ai_review/tests/fixtures/services/review/internal}/__init__.py +0 -0
  281. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/review/internal/inline.py +0 -0
  282. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/review/internal/inline_reply.py +0 -0
  283. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/review/internal/policy.py +0 -0
  284. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/review/internal/summary.py +0 -0
  285. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/review/internal/summary_reply.py +0 -0
  286. {xai_review-0.29.0/ai_review/tests/suites/clients/bitbucket → xai_review-0.31.0/ai_review/tests/fixtures/services/review/runner}/__init__.py +0 -0
  287. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/review/runner/context.py +0 -0
  288. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/review/runner/inline.py +0 -0
  289. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/review/runner/inline_reply.py +0 -0
  290. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/review/runner/summary.py +0 -0
  291. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/review/runner/summary_reply.py +0 -0
  292. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/fixtures/services/vcs.py +0 -0
  293. {xai_review-0.29.0/ai_review/tests/suites/clients/claude → xai_review-0.31.0/ai_review/tests/suites}/__init__.py +0 -0
  294. {xai_review-0.29.0/ai_review/tests/suites/clients/gemini → xai_review-0.31.0/ai_review/tests/suites/cli}/__init__.py +0 -0
  295. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/cli/test_main.py +0 -0
  296. {xai_review-0.29.0/ai_review/tests/suites/clients/github → xai_review-0.31.0/ai_review/tests/suites/clients}/__init__.py +0 -0
  297. {xai_review-0.29.0/ai_review/tests/suites/clients/gitlab → xai_review-0.31.0/ai_review/tests/suites/clients/bitbucket}/__init__.py +0 -0
  298. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/bitbucket/test_client.py +0 -0
  299. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/bitbucket/test_tools.py +0 -0
  300. {xai_review-0.29.0/ai_review/tests/suites/clients/ollama → xai_review-0.31.0/ai_review/tests/suites/clients/claude}/__init__.py +0 -0
  301. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/claude/test_client.py +0 -0
  302. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/claude/test_schema.py +0 -0
  303. {xai_review-0.29.0/ai_review/tests/suites/clients/openai → xai_review-0.31.0/ai_review/tests/suites/clients/gemini}/__init__.py +0 -0
  304. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/gemini/test_client.py +0 -0
  305. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/gemini/test_schema.py +0 -0
  306. {xai_review-0.29.0/ai_review/tests/suites/libs → xai_review-0.31.0/ai_review/tests/suites/clients/gitea}/__init__.py +0 -0
  307. {xai_review-0.29.0/ai_review/tests/suites/libs/asynchronous → xai_review-0.31.0/ai_review/tests/suites/clients/github}/__init__.py +0 -0
  308. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/github/test_client.py +0 -0
  309. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/github/test_tools.py +0 -0
  310. {xai_review-0.29.0/ai_review/tests/suites/libs/config → xai_review-0.31.0/ai_review/tests/suites/clients/gitlab}/__init__.py +0 -0
  311. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/gitlab/test_client.py +0 -0
  312. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/gitlab/test_tools.py +0 -0
  313. {xai_review-0.29.0/ai_review/tests/suites/libs/diff → xai_review-0.31.0/ai_review/tests/suites/clients/ollama}/__init__.py +0 -0
  314. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/ollama/test_client.py +0 -0
  315. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/ollama/test_schema.py +0 -0
  316. {xai_review-0.29.0/ai_review/tests/suites/libs/http → xai_review-0.31.0/ai_review/tests/suites/clients/openai}/__init__.py +0 -0
  317. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/openai/test_client.py +0 -0
  318. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/clients/openai/test_schema.py +0 -0
  319. {xai_review-0.29.0/ai_review/tests/suites/libs/llm → xai_review-0.31.0/ai_review/tests/suites/libs}/__init__.py +0 -0
  320. {xai_review-0.29.0/ai_review/tests/suites/libs/template → xai_review-0.31.0/ai_review/tests/suites/libs/asynchronous}/__init__.py +0 -0
  321. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/libs/asynchronous/test_gather.py +0 -0
  322. {xai_review-0.29.0/ai_review/tests/suites/services → xai_review-0.31.0/ai_review/tests/suites/libs/config}/__init__.py +0 -0
  323. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/libs/config/test_prompt.py +0 -0
  324. {xai_review-0.29.0/ai_review/tests/suites/services/cost → xai_review-0.31.0/ai_review/tests/suites/libs/diff}/__init__.py +0 -0
  325. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/libs/diff/test_models.py +0 -0
  326. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/libs/diff/test_parser.py +0 -0
  327. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/libs/diff/test_tools.py +0 -0
  328. {xai_review-0.29.0/ai_review/tests/suites/services/diff → xai_review-0.31.0/ai_review/tests/suites/libs/http}/__init__.py +0 -0
  329. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/libs/http/test_paginate.py +0 -0
  330. {xai_review-0.29.0/ai_review/tests/suites/services/hook → xai_review-0.31.0/ai_review/tests/suites/libs/llm}/__init__.py +0 -0
  331. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/libs/llm/test_output_json_parser.py +0 -0
  332. {xai_review-0.29.0/ai_review/tests/suites/services/llm → xai_review-0.31.0/ai_review/tests/suites/libs/template}/__init__.py +0 -0
  333. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/libs/template/test_render.py +0 -0
  334. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/libs/test_json.py +0 -0
  335. {xai_review-0.29.0/ai_review/tests/suites/services/llm/claude → xai_review-0.31.0/ai_review/tests/suites/services}/__init__.py +0 -0
  336. {xai_review-0.29.0/ai_review/tests/suites/services/llm/gemini → xai_review-0.31.0/ai_review/tests/suites/services/cost}/__init__.py +0 -0
  337. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/cost/test_schema.py +0 -0
  338. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/cost/test_service.py +0 -0
  339. {xai_review-0.29.0/ai_review/tests/suites/services/llm/ollama → xai_review-0.31.0/ai_review/tests/suites/services/diff}/__init__.py +0 -0
  340. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/diff/test_renderers.py +0 -0
  341. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/diff/test_service.py +0 -0
  342. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/diff/test_tools.py +0 -0
  343. {xai_review-0.29.0/ai_review/tests/suites/services/llm/openai → xai_review-0.31.0/ai_review/tests/suites/services/hook}/__init__.py +0 -0
  344. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/hook/test_service.py +0 -0
  345. {xai_review-0.29.0/ai_review/tests/suites/services/prompt → xai_review-0.31.0/ai_review/tests/suites/services/llm}/__init__.py +0 -0
  346. {xai_review-0.29.0/ai_review/tests/suites/services/review → xai_review-0.31.0/ai_review/tests/suites/services/llm/claude}/__init__.py +0 -0
  347. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/llm/claude/test_client.py +0 -0
  348. {xai_review-0.29.0/ai_review/tests/suites/services/review/gateway → xai_review-0.31.0/ai_review/tests/suites/services/llm/gemini}/__init__.py +0 -0
  349. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/llm/gemini/test_client.py +0 -0
  350. {xai_review-0.29.0/ai_review/tests/suites/services/review/internal → xai_review-0.31.0/ai_review/tests/suites/services/llm/ollama}/__init__.py +0 -0
  351. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/llm/ollama/test_client.py +0 -0
  352. {xai_review-0.29.0/ai_review/tests/suites/services/review/internal/inline → xai_review-0.31.0/ai_review/tests/suites/services/llm/openai}/__init__.py +0 -0
  353. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/llm/openai/test_client.py +0 -0
  354. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/llm/test_factory.py +0 -0
  355. {xai_review-0.29.0/ai_review/tests/suites/services/review/internal/inline_reply → xai_review-0.31.0/ai_review/tests/suites/services/prompt}/__init__.py +0 -0
  356. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/prompt/test_adapter.py +0 -0
  357. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/prompt/test_schema.py +0 -0
  358. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/prompt/test_service.py +0 -0
  359. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/prompt/test_tools.py +0 -0
  360. {xai_review-0.29.0/ai_review/tests/suites/services/review/internal/policy → xai_review-0.31.0/ai_review/tests/suites/services/review}/__init__.py +0 -0
  361. {xai_review-0.29.0/ai_review/tests/suites/services/review/internal/summary → xai_review-0.31.0/ai_review/tests/suites/services/review/gateway}/__init__.py +0 -0
  362. {xai_review-0.29.0/ai_review/tests/suites/services/review/internal/summary_reply → xai_review-0.31.0/ai_review/tests/suites/services/review/internal}/__init__.py +0 -0
  363. {xai_review-0.29.0/ai_review/tests/suites/services/review/runner → xai_review-0.31.0/ai_review/tests/suites/services/review/internal/inline}/__init__.py +0 -0
  364. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/internal/inline/test_schema.py +0 -0
  365. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/internal/inline/test_service.py +0 -0
  366. {xai_review-0.29.0/ai_review/tests/suites/services/vcs → xai_review-0.31.0/ai_review/tests/suites/services/review/internal/inline_reply}/__init__.py +0 -0
  367. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/internal/inline_reply/test_schema.py +0 -0
  368. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/internal/inline_reply/test_service.py +0 -0
  369. {xai_review-0.29.0/ai_review/tests/suites/services/vcs/bitbucket → xai_review-0.31.0/ai_review/tests/suites/services/review/internal/policy}/__init__.py +0 -0
  370. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/internal/policy/test_service.py +0 -0
  371. {xai_review-0.29.0/ai_review/tests/suites/services/vcs/github → xai_review-0.31.0/ai_review/tests/suites/services/review/internal/summary}/__init__.py +0 -0
  372. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/internal/summary/test_schema.py +0 -0
  373. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/internal/summary/test_service.py +0 -0
  374. {xai_review-0.29.0/ai_review/tests/suites/services/vcs/gitlab → xai_review-0.31.0/ai_review/tests/suites/services/review/internal/summary_reply}/__init__.py +0 -0
  375. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/internal/summary_reply/test_schema.py +0 -0
  376. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/review/internal/summary_reply/test_service.py +0 -0
  377. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/vcs/bitbucket/test_adapter.py +0 -0
  378. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/vcs/bitbucket/test_client.py +0 -0
  379. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/vcs/github/test_adapter.py +0 -0
  380. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/vcs/github/test_client.py +0 -0
  381. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/vcs/gitlab/test_adapter.py +0 -0
  382. {xai_review-0.29.0 → xai_review-0.31.0}/ai_review/tests/suites/services/vcs/gitlab/test_client.py +0 -0
  383. {xai_review-0.29.0 → xai_review-0.31.0}/setup.cfg +0 -0
  384. {xai_review-0.29.0 → xai_review-0.31.0}/xai_review.egg-info/dependency_links.txt +0 -0
  385. {xai_review-0.29.0 → xai_review-0.31.0}/xai_review.egg-info/entry_points.txt +0 -0
  386. {xai_review-0.29.0 → xai_review-0.31.0}/xai_review.egg-info/requires.txt +0 -0
  387. {xai_review-0.29.0 → xai_review-0.31.0}/xai_review.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xai-review
3
- Version: 0.29.0
3
+ Version: 0.31.0
4
4
  Summary: AI-powered code review tool
5
5
  Author-email: Nikita Filonov <nikita.filonov@example.com>
6
6
  Maintainer-email: Nikita Filonov <nikita.filonov@example.com>
@@ -67,15 +67,15 @@ improve code quality, enforce consistency, and speed up the review process.
67
67
  ✨ Key features:
68
68
 
69
69
  - **Multiple LLM providers** — choose between **OpenAI**, **Claude**, **Gemini**, or **Ollama**, and switch anytime.
70
- - **VCS integration** — works out of the box with **GitLab**, **GitHub**, and **Bitbucket**.
70
+ - **VCS integration** — works out of the box with **GitLab**, **GitHub**, **Bitbucket**, and **Gitea**.
71
71
  - **Customizable prompts** — adapt inline, context, and summary reviews to match your team’s coding guidelines.
72
72
  - **Reply modes** — AI can now **participate in existing review threads**, adding follow-up replies in both inline and
73
73
  summary discussions.
74
74
  - **Flexible configuration** — supports `YAML`, `JSON`, and `ENV`, with seamless overrides in CI/CD pipelines.
75
75
  - **AI Review runs fully client-side** — it never proxies or inspects your requests.
76
76
 
77
- AI Review runs automatically in your CI/CD pipeline and posts both **inline comments**, **summary reviews**, and now *
78
- *AI-generated replies** directly inside your merge requests. This makes reviews faster, more conversational, and still
77
+ AI Review runs automatically in your CI/CD pipeline and posts both **inline comments**, **summary reviews**, and now
78
+ **AI-generated replies** directly inside your merge requests. This makes reviews faster, more conversational, and still
79
79
  fully under human control.
80
80
 
81
81
  ---
@@ -85,11 +85,13 @@ fully under human control.
85
85
  Curious how **AI Review** works in practice? Here are three real Pull Requests reviewed entirely by the tool — one per
86
86
  mode:
87
87
 
88
- | Mode | Description | 🐙 GitHub | 🦊 GitLab |
89
- |------------|----------------------------------------------------|----------------------------------------------------------------------|----------------------------------------------------------------------------|
90
- | 🧩 Inline | Adds line-by-line comments directly in the diff | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/4) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/2) |
91
- | 🧠 Context | Performs broader analysis across multiple files | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/5) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/3) |
92
- | 📄 Summary | Posts a concise summary review with key highlights | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/6) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/4) |
88
+ | Mode | Description | 🐙 GitHub | 🦊 GitLab |
89
+ |------------------|----------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------|----------------------------------------------------------------------------|
90
+ | 🧩 Inline | Adds **line-by-line comments** directly in the diff. Focuses on specific code changes. | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/4) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/2) |
91
+ | 🧠 Context | Performs a **broader analysis across multiple files**, detecting cross-file issues and inconsistencies. | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/5) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/3) |
92
+ | 📄 Summary | Posts a **concise high-level summary** with key highlights, strengths, and major issues. | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/6) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/4) |
93
+ | 💬 Inline Reply | Generates a **context-aware reply** to an existing inline comment thread. Can clarify decisions, propose fixes, or provide code suggestions. | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/16) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/5) |
94
+ | 💬 Summary Reply | Continues the **summary-level review discussion**, responding to reviewer comments with clarifications, rationale, or actionable next steps. | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/17) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/6) |
93
95
 
94
96
  👉 Each review was generated automatically via GitHub Actions using the corresponding mode:
95
97
 
@@ -97,6 +99,8 @@ mode:
97
99
  ai-review run-inline
98
100
  ai-review run-summary
99
101
  ai-review run-context
102
+ ai-review run-inline-reply
103
+ ai-review run-summary-reply
100
104
  ```
101
105
 
102
106
  ---
@@ -162,6 +166,8 @@ vcs:
162
166
  > - ai-review run-inline
163
167
  > - ai-review run-context
164
168
  > - ai-review run-summary
169
+ > - ai-review run-inline-reply
170
+ > - ai-review run-summary-reply
165
171
 
166
172
  ---
167
173
 
@@ -172,7 +178,7 @@ Key things you can customize:
172
178
 
173
179
  - **LLM provider** — OpenAI, Gemini, Claude, or Ollama
174
180
  - **Model settings** — model name, temperature, max tokens
175
- - **VCS integration** — works out of the box with **GitLab**, **GitHub**, and **Bitbucket**
181
+ - **VCS integration** — works out of the box with **GitLab**, **GitHub**, **Bitbucket**, and **Gitea**
176
182
  - **Review policy** — which files to include/exclude, review modes
177
183
  - **Prompts** — inline/context/summary prompt templates
178
184
 
@@ -202,7 +208,7 @@ on:
202
208
  review-command:
203
209
  type: choice
204
210
  default: run
205
- options: [ run, run-inline, run-context, run-summary ]
211
+ options: [ run, run-inline, run-context, run-summary, run-inline-reply, run-summary-reply ]
206
212
  pull-request-number:
207
213
  type: string
208
214
  required: true
@@ -211,7 +217,10 @@ jobs:
211
217
  runs-on: ubuntu-latest
212
218
  steps:
213
219
  - uses: actions/checkout@v4
214
- - uses: Nikita-Filonov/ai-review@v0.29.0
220
+ with:
221
+ fetch-depth: 0
222
+
223
+ - uses: Nikita-Filonov/ai-review@v0.31.0
215
224
  with:
216
225
  review-command: ${{ inputs.review-command }}
217
226
  env:
@@ -33,15 +33,15 @@ improve code quality, enforce consistency, and speed up the review process.
33
33
  ✨ Key features:
34
34
 
35
35
  - **Multiple LLM providers** — choose between **OpenAI**, **Claude**, **Gemini**, or **Ollama**, and switch anytime.
36
- - **VCS integration** — works out of the box with **GitLab**, **GitHub**, and **Bitbucket**.
36
+ - **VCS integration** — works out of the box with **GitLab**, **GitHub**, **Bitbucket**, and **Gitea**.
37
37
  - **Customizable prompts** — adapt inline, context, and summary reviews to match your team’s coding guidelines.
38
38
  - **Reply modes** — AI can now **participate in existing review threads**, adding follow-up replies in both inline and
39
39
  summary discussions.
40
40
  - **Flexible configuration** — supports `YAML`, `JSON`, and `ENV`, with seamless overrides in CI/CD pipelines.
41
41
  - **AI Review runs fully client-side** — it never proxies or inspects your requests.
42
42
 
43
- AI Review runs automatically in your CI/CD pipeline and posts both **inline comments**, **summary reviews**, and now *
44
- *AI-generated replies** directly inside your merge requests. This makes reviews faster, more conversational, and still
43
+ AI Review runs automatically in your CI/CD pipeline and posts both **inline comments**, **summary reviews**, and now
44
+ **AI-generated replies** directly inside your merge requests. This makes reviews faster, more conversational, and still
45
45
  fully under human control.
46
46
 
47
47
  ---
@@ -51,11 +51,13 @@ fully under human control.
51
51
  Curious how **AI Review** works in practice? Here are three real Pull Requests reviewed entirely by the tool — one per
52
52
  mode:
53
53
 
54
- | Mode | Description | 🐙 GitHub | 🦊 GitLab |
55
- |------------|----------------------------------------------------|----------------------------------------------------------------------|----------------------------------------------------------------------------|
56
- | 🧩 Inline | Adds line-by-line comments directly in the diff | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/4) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/2) |
57
- | 🧠 Context | Performs broader analysis across multiple files | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/5) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/3) |
58
- | 📄 Summary | Posts a concise summary review with key highlights | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/6) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/4) |
54
+ | Mode | Description | 🐙 GitHub | 🦊 GitLab |
55
+ |------------------|----------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------|----------------------------------------------------------------------------|
56
+ | 🧩 Inline | Adds **line-by-line comments** directly in the diff. Focuses on specific code changes. | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/4) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/2) |
57
+ | 🧠 Context | Performs a **broader analysis across multiple files**, detecting cross-file issues and inconsistencies. | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/5) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/3) |
58
+ | 📄 Summary | Posts a **concise high-level summary** with key highlights, strengths, and major issues. | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/6) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/4) |
59
+ | 💬 Inline Reply | Generates a **context-aware reply** to an existing inline comment thread. Can clarify decisions, propose fixes, or provide code suggestions. | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/16) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/5) |
60
+ | 💬 Summary Reply | Continues the **summary-level review discussion**, responding to reviewer comments with clarifications, rationale, or actionable next steps. | [View on GitHub](https://github.com/Nikita-Filonov/ai-review/pull/17) | [View on GitLab](https://gitlab.com/core8332439/review/-/merge_requests/6) |
59
61
 
60
62
  👉 Each review was generated automatically via GitHub Actions using the corresponding mode:
61
63
 
@@ -63,6 +65,8 @@ mode:
63
65
  ai-review run-inline
64
66
  ai-review run-summary
65
67
  ai-review run-context
68
+ ai-review run-inline-reply
69
+ ai-review run-summary-reply
66
70
  ```
67
71
 
68
72
  ---
@@ -128,6 +132,8 @@ vcs:
128
132
  > - ai-review run-inline
129
133
  > - ai-review run-context
130
134
  > - ai-review run-summary
135
+ > - ai-review run-inline-reply
136
+ > - ai-review run-summary-reply
131
137
 
132
138
  ---
133
139
 
@@ -138,7 +144,7 @@ Key things you can customize:
138
144
 
139
145
  - **LLM provider** — OpenAI, Gemini, Claude, or Ollama
140
146
  - **Model settings** — model name, temperature, max tokens
141
- - **VCS integration** — works out of the box with **GitLab**, **GitHub**, and **Bitbucket**
147
+ - **VCS integration** — works out of the box with **GitLab**, **GitHub**, **Bitbucket**, and **Gitea**
142
148
  - **Review policy** — which files to include/exclude, review modes
143
149
  - **Prompts** — inline/context/summary prompt templates
144
150
 
@@ -168,7 +174,7 @@ on:
168
174
  review-command:
169
175
  type: choice
170
176
  default: run
171
- options: [ run, run-inline, run-context, run-summary ]
177
+ options: [ run, run-inline, run-context, run-summary, run-inline-reply, run-summary-reply ]
172
178
  pull-request-number:
173
179
  type: string
174
180
  required: true
@@ -177,7 +183,10 @@ jobs:
177
183
  runs-on: ubuntu-latest
178
184
  steps:
179
185
  - uses: actions/checkout@v4
180
- - uses: Nikita-Filonov/ai-review@v0.29.0
186
+ with:
187
+ fetch-depth: 0
188
+
189
+ - uses: Nikita-Filonov/ai-review@v0.31.0
181
190
  with:
182
191
  review-command: ${{ inputs.review-command }}
183
192
  env:
@@ -0,0 +1,31 @@
1
+ from ai_review.clients.gitea.pr.client import GiteaPullRequestsHTTPClient
2
+ from httpx import AsyncClient, AsyncHTTPTransport
3
+
4
+ from ai_review.config import settings
5
+ from ai_review.libs.http.event_hooks.logger import LoggerEventHook
6
+ from ai_review.libs.http.transports.retry import RetryTransport
7
+ from ai_review.libs.logger import get_logger
8
+
9
+
10
+ class GiteaHTTPClient:
11
+ def __init__(self, client: AsyncClient):
12
+ self.pr = GiteaPullRequestsHTTPClient(client)
13
+
14
+
15
+ def get_gitea_http_client() -> GiteaHTTPClient:
16
+ logger = get_logger("GITEA_HTTP_CLIENT")
17
+ logger_event_hook = LoggerEventHook(logger=logger)
18
+ retry_transport = RetryTransport(logger=logger, transport=AsyncHTTPTransport())
19
+
20
+ client = AsyncClient(
21
+ timeout=settings.llm.http_client.timeout,
22
+ headers={"Authorization": f"token {settings.vcs.http_client.api_token_value}"},
23
+ base_url=settings.vcs.http_client.api_url_value.rstrip("/"),
24
+ transport=retry_transport,
25
+ event_hooks={
26
+ "request": [logger_event_hook.request],
27
+ "response": [logger_event_hook.response]
28
+ }
29
+ )
30
+
31
+ return GiteaHTTPClient(client=client)
@@ -0,0 +1,118 @@
1
+ from httpx import Response, QueryParams
2
+
3
+ from ai_review.clients.gitea.pr.schema.comments import (
4
+ GiteaPRCommentSchema,
5
+ GiteaGetPRCommentsQuerySchema,
6
+ GiteaGetPRCommentsResponseSchema,
7
+ GiteaCreateCommentRequestSchema,
8
+ GiteaCreateCommentResponseSchema
9
+ )
10
+ from ai_review.clients.gitea.pr.schema.files import (
11
+ GiteaPRFileSchema,
12
+ GiteaGetPRFilesQuerySchema,
13
+ GiteaGetPRFilesResponseSchema
14
+ )
15
+ from ai_review.clients.gitea.pr.schema.pull_request import GiteaGetPRResponseSchema
16
+ from ai_review.clients.gitea.pr.types import GiteaPullRequestsHTTPClientProtocol
17
+ from ai_review.clients.gitea.tools import gitea_has_next_page
18
+ from ai_review.config import settings
19
+ from ai_review.libs.http.client import HTTPClient
20
+ from ai_review.libs.http.handlers import HTTPClientError, handle_http_error
21
+ from ai_review.libs.http.paginate import paginate
22
+
23
+
24
+ class GiteaPullRequestsHTTPClientError(HTTPClientError):
25
+ pass
26
+
27
+
28
+ class GiteaPullRequestsHTTPClient(HTTPClient, GiteaPullRequestsHTTPClientProtocol):
29
+ @handle_http_error(client="GiteaPullRequestsHTTPClient", exception=GiteaPullRequestsHTTPClientError)
30
+ async def get_pull_request_api(self, owner: str, repo: str, pull_number: str) -> Response:
31
+ return await self.get(f"/repos/{owner}/{repo}/pulls/{pull_number}")
32
+
33
+ @handle_http_error(client="GiteaPullRequestsHTTPClient", exception=GiteaPullRequestsHTTPClientError)
34
+ async def get_files_api(
35
+ self,
36
+ owner: str,
37
+ repo: str,
38
+ pull_number: str,
39
+ query: GiteaGetPRFilesQuerySchema
40
+ ) -> Response:
41
+ return await self.get(
42
+ f"/repos/{owner}/{repo}/pulls/{pull_number}/files",
43
+ query=QueryParams(**query.model_dump())
44
+ )
45
+
46
+ @handle_http_error(client="GiteaPullRequestsHTTPClient", exception=GiteaPullRequestsHTTPClientError)
47
+ async def get_comments_api(
48
+ self,
49
+ owner: str,
50
+ repo: str,
51
+ pull_number: str,
52
+ query: GiteaGetPRCommentsQuerySchema
53
+ ) -> Response:
54
+ return await self.get(
55
+ f"/repos/{owner}/{repo}/issues/{pull_number}/comments",
56
+ query=QueryParams(**query.model_dump())
57
+ )
58
+
59
+ @handle_http_error(client="GiteaPullRequestsHTTPClient", exception=GiteaPullRequestsHTTPClientError)
60
+ async def create_comment_api(
61
+ self,
62
+ owner: str,
63
+ repo: str,
64
+ pull_number: str,
65
+ request: GiteaCreateCommentRequestSchema
66
+ ) -> Response:
67
+ return await self.post(
68
+ f"/repos/{owner}/{repo}/issues/{pull_number}/comments",
69
+ json=request.model_dump(),
70
+ )
71
+
72
+ async def get_pull_request(self, owner: str, repo: str, pull_number: str) -> GiteaGetPRResponseSchema:
73
+ response = await self.get_pull_request_api(owner, repo, pull_number)
74
+ return GiteaGetPRResponseSchema.model_validate_json(response.text)
75
+
76
+ async def get_files(self, owner: str, repo: str, pull_number: str) -> GiteaGetPRFilesResponseSchema:
77
+ async def fetch_page(page: int) -> Response:
78
+ query = GiteaGetPRFilesQuerySchema(page=page, per_page=settings.vcs.pagination.per_page)
79
+ return await self.get_files_api(owner, repo, pull_number, query)
80
+
81
+ def extract_items(response: Response) -> list[GiteaPRFileSchema]:
82
+ result = GiteaGetPRFilesResponseSchema.model_validate_json(response.text)
83
+ return result.root
84
+
85
+ items = await paginate(
86
+ max_pages=settings.vcs.pagination.max_pages,
87
+ fetch_page=fetch_page,
88
+ extract_items=extract_items,
89
+ has_next_page=gitea_has_next_page
90
+ )
91
+ return GiteaGetPRFilesResponseSchema(root=items)
92
+
93
+ async def get_comments(self, owner: str, repo: str, pull_number: str) -> GiteaGetPRCommentsResponseSchema:
94
+ async def fetch_page(page: int) -> Response:
95
+ query = GiteaGetPRCommentsQuerySchema(page=page, per_page=settings.vcs.pagination.per_page)
96
+ return await self.get_comments_api(owner, repo, pull_number, query)
97
+
98
+ def extract_items(response: Response) -> list[GiteaPRCommentSchema]:
99
+ result = GiteaGetPRCommentsResponseSchema.model_validate_json(response.text)
100
+ return result.root
101
+
102
+ items = await paginate(
103
+ max_pages=settings.vcs.pagination.max_pages,
104
+ fetch_page=fetch_page,
105
+ extract_items=extract_items,
106
+ has_next_page=gitea_has_next_page
107
+ )
108
+ return GiteaGetPRCommentsResponseSchema(root=items)
109
+
110
+ async def create_comment(
111
+ self,
112
+ owner: str,
113
+ repo: str,
114
+ pull_number: str,
115
+ request: GiteaCreateCommentRequestSchema
116
+ ) -> GiteaCreateCommentResponseSchema:
117
+ response = await self.create_comment_api(owner, repo, pull_number, request)
118
+ return GiteaCreateCommentResponseSchema.model_validate_json(response.text)
@@ -0,0 +1,37 @@
1
+ from pydantic import BaseModel, RootModel
2
+
3
+ from ai_review.clients.gitea.pr.schema.user import GiteaUserSchema
4
+
5
+
6
+ class GiteaPRCommentSchema(BaseModel):
7
+ id: int
8
+ body: str
9
+ path: str | None = None
10
+ line: int | None = None
11
+ user: GiteaUserSchema | None = None
12
+ resolver: GiteaUserSchema | None = None
13
+ position: int | None = None
14
+ commit_id: str | None = None
15
+ original_position: int | None = None
16
+ original_commit_id: str | None = None
17
+ pull_request_review_id: int | None = None
18
+
19
+
20
+ class GiteaGetPRCommentsQuerySchema(BaseModel):
21
+ page: int = 1
22
+ per_page: int = 100
23
+
24
+
25
+ class GiteaGetPRCommentsResponseSchema(RootModel[list[GiteaPRCommentSchema]]):
26
+ root: list[GiteaPRCommentSchema]
27
+
28
+
29
+ class GiteaCreateCommentRequestSchema(BaseModel):
30
+ body: str
31
+ path: str | None = None
32
+ line: int | None = None
33
+
34
+
35
+ class GiteaCreateCommentResponseSchema(BaseModel):
36
+ id: int
37
+ body: str
@@ -0,0 +1,16 @@
1
+ from pydantic import BaseModel, RootModel
2
+
3
+
4
+ class GiteaPRFileSchema(BaseModel):
5
+ patch: str | None = None
6
+ status: str
7
+ filename: str
8
+
9
+
10
+ class GiteaGetPRFilesQuerySchema(BaseModel):
11
+ page: int = 1
12
+ per_page: int = 100
13
+
14
+
15
+ class GiteaGetPRFilesResponseSchema(RootModel[list[GiteaPRFileSchema]]):
16
+ root: list[GiteaPRFileSchema]
@@ -0,0 +1,18 @@
1
+ from pydantic import BaseModel
2
+
3
+ from ai_review.clients.gitea.pr.schema.user import GiteaUserSchema
4
+
5
+
6
+ class GiteaBranchSchema(BaseModel):
7
+ ref: str
8
+ sha: str
9
+
10
+
11
+ class GiteaGetPRResponseSchema(BaseModel):
12
+ id: int
13
+ number: int
14
+ title: str
15
+ body: str | None = None
16
+ user: GiteaUserSchema
17
+ base: GiteaBranchSchema
18
+ head: GiteaBranchSchema
@@ -0,0 +1,6 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class GiteaUserSchema(BaseModel):
5
+ id: int
6
+ login: str
@@ -0,0 +1,25 @@
1
+ from typing import Protocol
2
+
3
+ from ai_review.clients.gitea.pr.schema.comments import (
4
+ GiteaCreateCommentRequestSchema,
5
+ GiteaCreateCommentResponseSchema,
6
+ GiteaGetPRCommentsResponseSchema
7
+ )
8
+ from ai_review.clients.gitea.pr.schema.files import GiteaGetPRFilesResponseSchema
9
+ from ai_review.clients.gitea.pr.schema.pull_request import GiteaGetPRResponseSchema
10
+
11
+
12
+ class GiteaPullRequestsHTTPClientProtocol(Protocol):
13
+ async def get_pull_request(self, owner: str, repo: str, pull_number: str) -> GiteaGetPRResponseSchema: ...
14
+
15
+ async def get_files(self, owner: str, repo: str, pull_number: str) -> GiteaGetPRFilesResponseSchema: ...
16
+
17
+ async def get_comments(self, owner: str, repo: str, pull_number: str) -> GiteaGetPRCommentsResponseSchema: ...
18
+
19
+ async def create_comment(
20
+ self,
21
+ owner: str,
22
+ repo: str,
23
+ pull_number: str,
24
+ request: GiteaCreateCommentRequestSchema
25
+ ) -> GiteaCreateCommentResponseSchema: ...
@@ -0,0 +1,6 @@
1
+ from httpx import Response
2
+
3
+
4
+ def gitea_has_next_page(response: Response) -> bool:
5
+ link_header = response.headers.get("Link")
6
+ return link_header is not None and 'rel="next"' in link_header
@@ -19,6 +19,7 @@ class ReviewMode(StrEnum):
19
19
 
20
20
  class ReviewConfig(BaseModel):
21
21
  mode: ReviewMode = ReviewMode.FULL_FILE_DIFF
22
+ dry_run: bool = False
22
23
  inline_tag: str = Field(default="#ai-review-inline")
23
24
  inline_reply_tag: str = Field(default="#ai-review-inline-reply")
24
25
  summary_tag: str = Field(default="#ai-review-summary")
@@ -3,6 +3,7 @@ from typing import Annotated, Literal
3
3
  from pydantic import BaseModel, Field
4
4
 
5
5
  from ai_review.libs.config.vcs.bitbucket import BitbucketPipelineConfig, BitbucketHTTPClientConfig
6
+ from ai_review.libs.config.vcs.gitea import GiteaPipelineConfig, GiteaHTTPClientConfig
6
7
  from ai_review.libs.config.vcs.github import GitHubPipelineConfig, GitHubHTTPClientConfig
7
8
  from ai_review.libs.config.vcs.gitlab import GitLabPipelineConfig, GitLabHTTPClientConfig
8
9
  from ai_review.libs.config.vcs.pagination import VCSPaginationConfig
@@ -14,6 +15,12 @@ class VCSConfigBase(BaseModel):
14
15
  pagination: VCSPaginationConfig = VCSPaginationConfig()
15
16
 
16
17
 
18
+ class GiteaVCSConfig(VCSConfigBase):
19
+ provider: Literal[VCSProvider.GITEA]
20
+ pipeline: GiteaPipelineConfig
21
+ http_client: GiteaHTTPClientConfig
22
+
23
+
17
24
  class GitLabVCSConfig(VCSConfigBase):
18
25
  provider: Literal[VCSProvider.GITLAB]
19
26
  pipeline: GitLabPipelineConfig
@@ -33,6 +40,6 @@ class BitbucketVCSConfig(VCSConfigBase):
33
40
 
34
41
 
35
42
  VCSConfig = Annotated[
36
- GitLabVCSConfig | GitHubVCSConfig | BitbucketVCSConfig,
43
+ GiteaVCSConfig | GitLabVCSConfig | GitHubVCSConfig | BitbucketVCSConfig,
37
44
  Field(discriminator="provider")
38
45
  ]
@@ -0,0 +1,13 @@
1
+ from pydantic import BaseModel
2
+
3
+ from ai_review.libs.config.http import HTTPClientWithTokenConfig
4
+
5
+
6
+ class GiteaPipelineConfig(BaseModel):
7
+ repo: str
8
+ owner: str
9
+ pull_number: str
10
+
11
+
12
+ class GiteaHTTPClientConfig(HTTPClientWithTokenConfig):
13
+ pass
@@ -2,6 +2,7 @@ from enum import StrEnum
2
2
 
3
3
 
4
4
  class VCSProvider(StrEnum):
5
+ GITEA = "GITEA"
5
6
  GITHUB = "GITHUB"
6
7
  GITLAB = "GITLAB"
7
8
  BITBUCKET = "BITBUCKET"
@@ -0,0 +1,42 @@
1
+ from ai_review.libs.asynchronous.gather import bounded_gather
2
+ from ai_review.libs.logger import get_logger
3
+ from ai_review.services.hook import hook
4
+ from ai_review.services.review.gateway.review_comment_gateway import ReviewCommentGateway
5
+ from ai_review.services.review.internal.inline.schema import InlineCommentListSchema, InlineCommentSchema
6
+ from ai_review.services.review.internal.inline_reply.schema import InlineCommentReplySchema
7
+ from ai_review.services.review.internal.summary.schema import SummaryCommentSchema
8
+ from ai_review.services.review.internal.summary_reply.schema import SummaryCommentReplySchema
9
+ from ai_review.services.vcs.types import VCSClientProtocol
10
+
11
+ logger = get_logger("REVIEW_DRY_RUN_COMMENT_GATEWAY")
12
+
13
+
14
+ class ReviewDryRunCommentGateway(ReviewCommentGateway):
15
+ def __init__(self, vcs: VCSClientProtocol):
16
+ super().__init__(vcs)
17
+ logger.warning("Running in DRY RUN mode — no comments will be posted to VCS")
18
+
19
+ async def process_inline_reply(self, thread_id: str, reply: InlineCommentReplySchema) -> None:
20
+ await hook.emit_inline_comment_reply_start(reply)
21
+ logger.info(f"[dry-run] Would create inline reply for thread {thread_id}:\n{reply.body_with_tag}")
22
+ await hook.emit_inline_comment_reply_complete(reply)
23
+
24
+ async def process_summary_reply(self, thread_id: str, reply: SummaryCommentReplySchema) -> None:
25
+ await hook.emit_summary_comment_reply_start(reply)
26
+ logger.info(f"[dry-run] Would create summary reply for thread {thread_id}:\n{reply.body_with_tag}")
27
+ await hook.emit_summary_comment_reply_complete(reply)
28
+
29
+ async def process_inline_comment(self, comment: InlineCommentSchema) -> None:
30
+ await hook.emit_inline_comment_start(comment)
31
+ logger.info(
32
+ f"[dry-run] Would create inline comment for {comment.file}:{comment.line}:\n{comment.body_with_tag}"
33
+ )
34
+ await hook.emit_inline_comment_complete(comment)
35
+
36
+ async def process_summary_comment(self, comment: SummaryCommentSchema) -> None:
37
+ await hook.emit_summary_comment_start(comment)
38
+ logger.info(f"[dry-run] Would create summary comment:\n{comment.body_with_tag}")
39
+ await hook.emit_summary_comment_complete(comment)
40
+
41
+ async def process_inline_comments(self, comments: InlineCommentListSchema) -> None:
42
+ await bounded_gather([self.process_inline_comment(comment) for comment in comments.root])
@@ -1,3 +1,4 @@
1
+ from ai_review.config import settings
1
2
  from ai_review.libs.logger import get_logger
2
3
  from ai_review.services.artifacts.service import ArtifactsService
3
4
  from ai_review.services.cost.service import CostService
@@ -5,8 +6,9 @@ from ai_review.services.diff.service import DiffService
5
6
  from ai_review.services.git.service import GitService
6
7
  from ai_review.services.llm.factory import get_llm_client
7
8
  from ai_review.services.prompt.service import PromptService
8
- from ai_review.services.review.gateway.comment import ReviewCommentGateway
9
- from ai_review.services.review.gateway.llm import ReviewLLMGateway
9
+ from ai_review.services.review.gateway.review_comment_gateway import ReviewCommentGateway
10
+ from ai_review.services.review.gateway.review_dry_run_comment_gateway import ReviewDryRunCommentGateway
11
+ from ai_review.services.review.gateway.review_llm_gateway import ReviewLLMGateway
10
12
  from ai_review.services.review.internal.inline.service import InlineCommentService
11
13
  from ai_review.services.review.internal.inline_reply.service import InlineCommentReplyService
12
14
  from ai_review.services.review.internal.policy.service import ReviewPolicyService
@@ -42,7 +44,11 @@ class ReviewService:
42
44
  cost=self.cost,
43
45
  artifacts=self.artifacts
44
46
  )
45
- self.review_comment_gateway = ReviewCommentGateway(vcs=self.vcs)
47
+ self.review_comment_gateway = (
48
+ ReviewDryRunCommentGateway(vcs=self.vcs)
49
+ if settings.review.dry_run
50
+ else ReviewCommentGateway(vcs=self.vcs)
51
+ )
46
52
 
47
53
  self.inline_review_runner = InlineReviewRunner(
48
54
  vcs=self.vcs,
@@ -1,6 +1,7 @@
1
1
  from ai_review.config import settings
2
2
  from ai_review.libs.constants.vcs_provider import VCSProvider
3
3
  from ai_review.services.vcs.bitbucket.client import BitbucketVCSClient
4
+ from ai_review.services.vcs.gitea.client import GiteaVCSClient
4
5
  from ai_review.services.vcs.github.client import GitHubVCSClient
5
6
  from ai_review.services.vcs.gitlab.client import GitLabVCSClient
6
7
  from ai_review.services.vcs.types import VCSClientProtocol
@@ -8,6 +9,8 @@ from ai_review.services.vcs.types import VCSClientProtocol
8
9
 
9
10
  def get_vcs_client() -> VCSClientProtocol:
10
11
  match settings.vcs.provider:
12
+ case VCSProvider.GITEA:
13
+ return GiteaVCSClient()
11
14
  case VCSProvider.GITLAB:
12
15
  return GitLabVCSClient()
13
16
  case VCSProvider.GITHUB:
@@ -0,0 +1,22 @@
1
+ from ai_review.clients.gitea.pr.schema.comments import GiteaPRCommentSchema
2
+ from ai_review.clients.gitea.pr.schema.pull_request import GiteaUserSchema
3
+ from ai_review.services.vcs.types import ReviewCommentSchema, UserSchema
4
+
5
+
6
+ def get_user_from_gitea_user(user: GiteaUserSchema | None) -> UserSchema:
7
+ return UserSchema(
8
+ id=user.id if user else None,
9
+ name=user.login if user else "",
10
+ username=user.login if user else "",
11
+ )
12
+
13
+
14
+ def get_review_comment_from_gitea_comment(comment: GiteaPRCommentSchema) -> ReviewCommentSchema:
15
+ return ReviewCommentSchema(
16
+ id=comment.id,
17
+ body=comment.body or "",
18
+ file=comment.path,
19
+ line=comment.line,
20
+ author=get_user_from_gitea_user(comment.user),
21
+ thread_id=comment.id
22
+ )