xai-review 0.33.0__tar.gz → 0.35.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 (419) hide show
  1. {xai_review-0.33.0/xai_review.egg-info → xai_review-0.35.0}/PKG-INFO +11 -10
  2. {xai_review-0.33.0 → xai_review-0.35.0}/README.md +8 -7
  3. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/claude/client.py +1 -1
  4. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/claude/schema.py +2 -2
  5. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gemini/client.py +2 -1
  6. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gemini/schema.py +2 -2
  7. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/ollama/client.py +1 -1
  8. {xai_review-0.33.0/ai_review/clients/openai → xai_review-0.35.0/ai_review/clients/openai/v1}/client.py +9 -9
  9. {xai_review-0.33.0/ai_review/clients/openai → xai_review-0.35.0/ai_review/clients/openai/v1}/schema.py +1 -1
  10. xai_review-0.35.0/ai_review/clients/openai/v1/types.py +8 -0
  11. xai_review-0.35.0/ai_review/clients/openai/v2/client.py +46 -0
  12. xai_review-0.35.0/ai_review/clients/openai/v2/schema.py +47 -0
  13. xai_review-0.35.0/ai_review/clients/openai/v2/types.py +11 -0
  14. xai_review-0.35.0/ai_review/clients/openrouter/client.py +50 -0
  15. xai_review-0.35.0/ai_review/clients/openrouter/schema.py +36 -0
  16. xai_review-0.35.0/ai_review/clients/openrouter/types.py +11 -0
  17. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/llm/base.py +8 -1
  18. xai_review-0.35.0/ai_review/libs/config/llm/meta.py +7 -0
  19. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/llm/openai.py +4 -0
  20. xai_review-0.35.0/ai_review/libs/config/llm/openrouter.py +12 -0
  21. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/constants/llm_provider.py +1 -0
  22. xai_review-0.35.0/ai_review/resources/pricing.yaml +93 -0
  23. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/llm/factory.py +3 -0
  24. xai_review-0.35.0/ai_review/services/llm/openai/client.py +56 -0
  25. {xai_review-0.33.0/ai_review/services/llm/openai → xai_review-0.35.0/ai_review/services/llm/openrouter}/client.py +10 -7
  26. xai_review-0.35.0/ai_review/tests/fixtures/clients/openai.py +141 -0
  27. xai_review-0.35.0/ai_review/tests/fixtures/clients/openrouter.py +72 -0
  28. xai_review-0.35.0/ai_review/tests/suites/clients/openai/v1/test_client.py +12 -0
  29. {xai_review-0.33.0/ai_review/tests/suites/clients/openai → xai_review-0.35.0/ai_review/tests/suites/clients/openai/v1}/test_schema.py +1 -1
  30. xai_review-0.35.0/ai_review/tests/suites/clients/openai/v2/test_client.py +12 -0
  31. xai_review-0.35.0/ai_review/tests/suites/clients/openai/v2/test_schema.py +80 -0
  32. xai_review-0.35.0/ai_review/tests/suites/clients/openrouter/test_client.py +12 -0
  33. xai_review-0.35.0/ai_review/tests/suites/clients/openrouter/test_schema.py +57 -0
  34. xai_review-0.35.0/ai_review/tests/suites/libs/config/llm/test_openai.py +28 -0
  35. xai_review-0.35.0/ai_review/tests/suites/services/llm/openai/test_client.py +39 -0
  36. xai_review-0.35.0/ai_review/tests/suites/services/llm/openrouter/test_client.py +22 -0
  37. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/llm/test_factory.py +8 -1
  38. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/gateway/test_review_comment_gateway.py +5 -5
  39. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/gateway/test_review_dry_run_comment_gateway.py +5 -5
  40. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/gateway/test_review_llm_gateway.py +2 -2
  41. xai_review-0.35.0/ai_review/tests/suites/services/review/internal/policy/__init__.py +0 -0
  42. xai_review-0.35.0/ai_review/tests/suites/services/review/internal/summary/__init__.py +0 -0
  43. xai_review-0.35.0/ai_review/tests/suites/services/review/internal/summary_reply/__init__.py +0 -0
  44. xai_review-0.35.0/ai_review/tests/suites/services/review/runner/__init__.py +0 -0
  45. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/test_service.py +2 -2
  46. xai_review-0.35.0/ai_review/tests/suites/services/vcs/__init__.py +0 -0
  47. xai_review-0.35.0/ai_review/tests/suites/services/vcs/bitbucket/__init__.py +0 -0
  48. xai_review-0.35.0/ai_review/tests/suites/services/vcs/gitea/__init__.py +0 -0
  49. xai_review-0.35.0/ai_review/tests/suites/services/vcs/github/__init__.py +0 -0
  50. xai_review-0.35.0/ai_review/tests/suites/services/vcs/gitlab/__init__.py +0 -0
  51. {xai_review-0.33.0 → xai_review-0.35.0}/pyproject.toml +17 -3
  52. {xai_review-0.33.0 → xai_review-0.35.0/xai_review.egg-info}/PKG-INFO +11 -10
  53. {xai_review-0.33.0 → xai_review-0.35.0}/xai_review.egg-info/SOURCES.txt +29 -5
  54. xai_review-0.33.0/ai_review/clients/openai/types.py +0 -8
  55. xai_review-0.33.0/ai_review/libs/config/llm/meta.py +0 -7
  56. xai_review-0.33.0/ai_review/resources/pricing.yaml +0 -55
  57. xai_review-0.33.0/ai_review/tests/fixtures/clients/openai.py +0 -69
  58. xai_review-0.33.0/ai_review/tests/suites/clients/openai/test_client.py +0 -12
  59. xai_review-0.33.0/ai_review/tests/suites/services/llm/openai/test_client.py +0 -22
  60. {xai_review-0.33.0 → xai_review-0.35.0}/LICENSE +0 -0
  61. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/__init__.py +0 -0
  62. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/cli/__init__.py +0 -0
  63. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/cli/commands/__init__.py +0 -0
  64. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/cli/commands/run_context_review.py +0 -0
  65. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/cli/commands/run_inline_reply_review.py +0 -0
  66. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/cli/commands/run_inline_review.py +0 -0
  67. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/cli/commands/run_review.py +0 -0
  68. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/cli/commands/run_summary_reply_review.py +0 -0
  69. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/cli/commands/run_summary_review.py +0 -0
  70. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/cli/main.py +0 -0
  71. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/__init__.py +0 -0
  72. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/bitbucket/__init__.py +0 -0
  73. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/bitbucket/client.py +0 -0
  74. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/bitbucket/pr/__init__.py +0 -0
  75. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/bitbucket/pr/client.py +0 -0
  76. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/bitbucket/pr/schema/__init__.py +0 -0
  77. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/bitbucket/pr/schema/comments.py +0 -0
  78. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/bitbucket/pr/schema/files.py +0 -0
  79. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/bitbucket/pr/schema/pull_request.py +0 -0
  80. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/bitbucket/pr/schema/user.py +0 -0
  81. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/bitbucket/pr/types.py +0 -0
  82. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/bitbucket/tools.py +0 -0
  83. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/claude/__init__.py +0 -0
  84. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/claude/types.py +0 -0
  85. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gemini/__init__.py +0 -0
  86. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gemini/types.py +0 -0
  87. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitea/__init__.py +0 -0
  88. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitea/client.py +0 -0
  89. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitea/pr/__init__.py +0 -0
  90. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitea/pr/client.py +0 -0
  91. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitea/pr/schema/__init__.py +0 -0
  92. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitea/pr/schema/comments.py +0 -0
  93. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitea/pr/schema/files.py +0 -0
  94. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitea/pr/schema/pull_request.py +0 -0
  95. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitea/pr/schema/user.py +0 -0
  96. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitea/pr/types.py +0 -0
  97. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitea/tools.py +0 -0
  98. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/github/__init__.py +0 -0
  99. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/github/client.py +0 -0
  100. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/github/pr/__init__.py +0 -0
  101. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/github/pr/client.py +0 -0
  102. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/github/pr/schema/__init__.py +0 -0
  103. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/github/pr/schema/comments.py +0 -0
  104. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/github/pr/schema/files.py +0 -0
  105. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/github/pr/schema/pull_request.py +0 -0
  106. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/github/pr/schema/reviews.py +0 -0
  107. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/github/pr/schema/user.py +0 -0
  108. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/github/pr/types.py +0 -0
  109. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/github/tools.py +0 -0
  110. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitlab/__init__.py +0 -0
  111. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitlab/client.py +0 -0
  112. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitlab/mr/__init__.py +0 -0
  113. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitlab/mr/client.py +0 -0
  114. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitlab/mr/schema/__init__.py +0 -0
  115. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitlab/mr/schema/changes.py +0 -0
  116. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitlab/mr/schema/discussions.py +0 -0
  117. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitlab/mr/schema/notes.py +0 -0
  118. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitlab/mr/schema/position.py +0 -0
  119. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitlab/mr/schema/user.py +0 -0
  120. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitlab/mr/types.py +0 -0
  121. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/gitlab/tools.py +0 -0
  122. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/ollama/__init__.py +0 -0
  123. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/ollama/schema.py +0 -0
  124. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/ollama/types.py +0 -0
  125. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/clients/openai/__init__.py +0 -0
  126. {xai_review-0.33.0/ai_review/libs → xai_review-0.35.0/ai_review/clients/openai/v1}/__init__.py +0 -0
  127. {xai_review-0.33.0/ai_review/libs/asynchronous → xai_review-0.35.0/ai_review/clients/openai/v2}/__init__.py +0 -0
  128. {xai_review-0.33.0/ai_review/libs/config → xai_review-0.35.0/ai_review/clients/openrouter}/__init__.py +0 -0
  129. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/config.py +0 -0
  130. {xai_review-0.33.0/ai_review/libs/config/llm → xai_review-0.35.0/ai_review/libs}/__init__.py +0 -0
  131. {xai_review-0.33.0/ai_review/libs/config/vcs → xai_review-0.35.0/ai_review/libs/asynchronous}/__init__.py +0 -0
  132. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/asynchronous/gather.py +0 -0
  133. {xai_review-0.33.0/ai_review/libs/constants → xai_review-0.35.0/ai_review/libs/config}/__init__.py +0 -0
  134. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/artifacts.py +0 -0
  135. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/base.py +0 -0
  136. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/core.py +0 -0
  137. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/http.py +0 -0
  138. {xai_review-0.33.0/ai_review/libs/diff → xai_review-0.35.0/ai_review/libs/config/llm}/__init__.py +0 -0
  139. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/llm/claude.py +0 -0
  140. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/llm/gemini.py +0 -0
  141. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/llm/ollama.py +0 -0
  142. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/logger.py +0 -0
  143. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/prompt.py +0 -0
  144. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/review.py +0 -0
  145. {xai_review-0.33.0/ai_review/libs/http → xai_review-0.35.0/ai_review/libs/config/vcs}/__init__.py +0 -0
  146. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/vcs/base.py +0 -0
  147. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/vcs/bitbucket.py +0 -0
  148. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/vcs/gitea.py +0 -0
  149. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/vcs/github.py +0 -0
  150. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/vcs/gitlab.py +0 -0
  151. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/config/vcs/pagination.py +0 -0
  152. {xai_review-0.33.0/ai_review/libs/http/event_hooks → xai_review-0.35.0/ai_review/libs/constants}/__init__.py +0 -0
  153. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/constants/vcs_provider.py +0 -0
  154. {xai_review-0.33.0/ai_review/libs/http/transports → xai_review-0.35.0/ai_review/libs/diff}/__init__.py +0 -0
  155. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/diff/models.py +0 -0
  156. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/diff/parser.py +0 -0
  157. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/diff/tools.py +0 -0
  158. {xai_review-0.33.0/ai_review/libs/llm → xai_review-0.35.0/ai_review/libs/http}/__init__.py +0 -0
  159. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/http/client.py +0 -0
  160. {xai_review-0.33.0/ai_review/libs/template → xai_review-0.35.0/ai_review/libs/http/event_hooks}/__init__.py +0 -0
  161. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/http/event_hooks/base.py +0 -0
  162. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/http/event_hooks/logger.py +0 -0
  163. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/http/handlers.py +0 -0
  164. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/http/paginate.py +0 -0
  165. {xai_review-0.33.0/ai_review/prompts → xai_review-0.35.0/ai_review/libs/http/transports}/__init__.py +0 -0
  166. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/http/transports/retry.py +0 -0
  167. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/json.py +0 -0
  168. {xai_review-0.33.0/ai_review/resources → xai_review-0.35.0/ai_review/libs/llm}/__init__.py +0 -0
  169. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/llm/output_json_parser.py +0 -0
  170. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/logger.py +0 -0
  171. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/resources.py +0 -0
  172. {xai_review-0.33.0/ai_review/services → xai_review-0.35.0/ai_review/libs/template}/__init__.py +0 -0
  173. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/libs/template/render.py +0 -0
  174. {xai_review-0.33.0/ai_review/services/artifacts → xai_review-0.35.0/ai_review/prompts}/__init__.py +0 -0
  175. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/prompts/default_context.md +0 -0
  176. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/prompts/default_inline.md +0 -0
  177. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/prompts/default_inline_reply.md +0 -0
  178. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/prompts/default_summary.md +0 -0
  179. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/prompts/default_summary_reply.md +0 -0
  180. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/prompts/default_system_context.md +0 -0
  181. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/prompts/default_system_inline.md +0 -0
  182. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/prompts/default_system_inline_reply.md +0 -0
  183. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/prompts/default_system_summary.md +0 -0
  184. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/prompts/default_system_summary_reply.md +0 -0
  185. {xai_review-0.33.0/ai_review/services/cost → xai_review-0.35.0/ai_review/resources}/__init__.py +0 -0
  186. {xai_review-0.33.0/ai_review/services/diff → xai_review-0.35.0/ai_review/services}/__init__.py +0 -0
  187. {xai_review-0.33.0/ai_review/services/git → xai_review-0.35.0/ai_review/services/artifacts}/__init__.py +0 -0
  188. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/artifacts/schema.py +0 -0
  189. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/artifacts/service.py +0 -0
  190. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/artifacts/tools.py +0 -0
  191. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/artifacts/types.py +0 -0
  192. {xai_review-0.33.0/ai_review/services/llm → xai_review-0.35.0/ai_review/services/cost}/__init__.py +0 -0
  193. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/cost/schema.py +0 -0
  194. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/cost/service.py +0 -0
  195. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/cost/types.py +0 -0
  196. {xai_review-0.33.0/ai_review/services/llm/claude → xai_review-0.35.0/ai_review/services/diff}/__init__.py +0 -0
  197. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/diff/renderers.py +0 -0
  198. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/diff/schema.py +0 -0
  199. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/diff/service.py +0 -0
  200. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/diff/tools.py +0 -0
  201. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/diff/types.py +0 -0
  202. {xai_review-0.33.0/ai_review/services/llm/gemini → xai_review-0.35.0/ai_review/services/git}/__init__.py +0 -0
  203. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/git/service.py +0 -0
  204. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/git/types.py +0 -0
  205. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/hook/__init__.py +0 -0
  206. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/hook/constants.py +0 -0
  207. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/hook/service.py +0 -0
  208. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/hook/types.py +0 -0
  209. {xai_review-0.33.0/ai_review/services/llm/ollama → xai_review-0.35.0/ai_review/services/llm}/__init__.py +0 -0
  210. {xai_review-0.33.0/ai_review/services/llm/openai → xai_review-0.35.0/ai_review/services/llm/claude}/__init__.py +0 -0
  211. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/llm/claude/client.py +0 -0
  212. {xai_review-0.33.0/ai_review/services/prompt → xai_review-0.35.0/ai_review/services/llm/gemini}/__init__.py +0 -0
  213. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/llm/gemini/client.py +0 -0
  214. {xai_review-0.33.0/ai_review/services/review → xai_review-0.35.0/ai_review/services/llm/ollama}/__init__.py +0 -0
  215. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/llm/ollama/client.py +0 -0
  216. {xai_review-0.33.0/ai_review/services/review/gateway → xai_review-0.35.0/ai_review/services/llm/openai}/__init__.py +0 -0
  217. {xai_review-0.33.0/ai_review/services/review/internal → xai_review-0.35.0/ai_review/services/llm/openrouter}/__init__.py +0 -0
  218. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/llm/types.py +0 -0
  219. {xai_review-0.33.0/ai_review/services/review/internal/inline → xai_review-0.35.0/ai_review/services/prompt}/__init__.py +0 -0
  220. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/prompt/adapter.py +0 -0
  221. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/prompt/schema.py +0 -0
  222. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/prompt/service.py +0 -0
  223. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/prompt/tools.py +0 -0
  224. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/prompt/types.py +0 -0
  225. {xai_review-0.33.0/ai_review/services/review/internal/inline_reply → xai_review-0.35.0/ai_review/services/review}/__init__.py +0 -0
  226. {xai_review-0.33.0/ai_review/services/review/internal/policy → xai_review-0.35.0/ai_review/services/review/gateway}/__init__.py +0 -0
  227. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/gateway/review_comment_gateway.py +0 -0
  228. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/gateway/review_dry_run_comment_gateway.py +0 -0
  229. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/gateway/review_llm_gateway.py +0 -0
  230. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/gateway/types.py +0 -0
  231. {xai_review-0.33.0/ai_review/services/review/internal/summary → xai_review-0.35.0/ai_review/services/review/internal}/__init__.py +0 -0
  232. {xai_review-0.33.0/ai_review/services/review/internal/summary_reply → xai_review-0.35.0/ai_review/services/review/internal/inline}/__init__.py +0 -0
  233. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/inline/schema.py +0 -0
  234. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/inline/service.py +0 -0
  235. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/inline/types.py +0 -0
  236. {xai_review-0.33.0/ai_review/services/review/runner → xai_review-0.35.0/ai_review/services/review/internal/inline_reply}/__init__.py +0 -0
  237. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/inline_reply/schema.py +0 -0
  238. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/inline_reply/service.py +0 -0
  239. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/inline_reply/types.py +0 -0
  240. {xai_review-0.33.0/ai_review/services/vcs → xai_review-0.35.0/ai_review/services/review/internal/policy}/__init__.py +0 -0
  241. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/policy/service.py +0 -0
  242. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/policy/types.py +0 -0
  243. {xai_review-0.33.0/ai_review/services/vcs/bitbucket → xai_review-0.35.0/ai_review/services/review/internal/summary}/__init__.py +0 -0
  244. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/summary/schema.py +0 -0
  245. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/summary/service.py +0 -0
  246. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/summary/types.py +0 -0
  247. {xai_review-0.33.0/ai_review/services/vcs/gitea → xai_review-0.35.0/ai_review/services/review/internal/summary_reply}/__init__.py +0 -0
  248. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/summary_reply/schema.py +0 -0
  249. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/summary_reply/service.py +0 -0
  250. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/internal/summary_reply/types.py +0 -0
  251. {xai_review-0.33.0/ai_review/services/vcs/github → xai_review-0.35.0/ai_review/services/review/runner}/__init__.py +0 -0
  252. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/runner/context.py +0 -0
  253. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/runner/inline.py +0 -0
  254. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/runner/inline_reply.py +0 -0
  255. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/runner/summary.py +0 -0
  256. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/runner/summary_reply.py +0 -0
  257. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/runner/types.py +0 -0
  258. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/review/service.py +0 -0
  259. {xai_review-0.33.0/ai_review/services/vcs/gitlab → xai_review-0.35.0/ai_review/services/vcs}/__init__.py +0 -0
  260. {xai_review-0.33.0/ai_review/tests → xai_review-0.35.0/ai_review/services/vcs/bitbucket}/__init__.py +0 -0
  261. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/vcs/bitbucket/adapter.py +0 -0
  262. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/vcs/bitbucket/client.py +0 -0
  263. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/vcs/factory.py +0 -0
  264. {xai_review-0.33.0/ai_review/tests/fixtures → xai_review-0.35.0/ai_review/services/vcs/gitea}/__init__.py +0 -0
  265. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/vcs/gitea/adapter.py +0 -0
  266. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/vcs/gitea/client.py +0 -0
  267. {xai_review-0.33.0/ai_review/tests/fixtures/clients → xai_review-0.35.0/ai_review/services/vcs/github}/__init__.py +0 -0
  268. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/vcs/github/adapter.py +0 -0
  269. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/vcs/github/client.py +0 -0
  270. {xai_review-0.33.0/ai_review/tests/fixtures/libs → xai_review-0.35.0/ai_review/services/vcs/gitlab}/__init__.py +0 -0
  271. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/vcs/gitlab/adapter.py +0 -0
  272. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/vcs/gitlab/client.py +0 -0
  273. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/services/vcs/types.py +0 -0
  274. {xai_review-0.33.0/ai_review/tests/fixtures/libs/llm → xai_review-0.35.0/ai_review/tests}/__init__.py +0 -0
  275. {xai_review-0.33.0/ai_review/tests/fixtures/services → xai_review-0.35.0/ai_review/tests/fixtures}/__init__.py +0 -0
  276. {xai_review-0.33.0/ai_review/tests/fixtures/services/review → xai_review-0.35.0/ai_review/tests/fixtures/clients}/__init__.py +0 -0
  277. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/clients/bitbucket.py +0 -0
  278. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/clients/claude.py +0 -0
  279. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/clients/gemini.py +0 -0
  280. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/clients/gitea.py +0 -0
  281. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/clients/github.py +0 -0
  282. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/clients/gitlab.py +0 -0
  283. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/clients/ollama.py +0 -0
  284. {xai_review-0.33.0/ai_review/tests/fixtures/services/review/gateway → xai_review-0.35.0/ai_review/tests/fixtures/libs}/__init__.py +0 -0
  285. {xai_review-0.33.0/ai_review/tests/fixtures/services/review/internal → xai_review-0.35.0/ai_review/tests/fixtures/libs/llm}/__init__.py +0 -0
  286. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/libs/llm/output_json_parser.py +0 -0
  287. {xai_review-0.33.0/ai_review/tests/fixtures/services/review/runner → xai_review-0.35.0/ai_review/tests/fixtures/services}/__init__.py +0 -0
  288. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/artifacts.py +0 -0
  289. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/cost.py +0 -0
  290. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/diff.py +0 -0
  291. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/git.py +0 -0
  292. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/hook.py +0 -0
  293. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/llm.py +0 -0
  294. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/prompt.py +0 -0
  295. {xai_review-0.33.0/ai_review/tests/suites → xai_review-0.35.0/ai_review/tests/fixtures/services/review}/__init__.py +0 -0
  296. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/base.py +0 -0
  297. {xai_review-0.33.0/ai_review/tests/suites/cli → xai_review-0.35.0/ai_review/tests/fixtures/services/review/gateway}/__init__.py +0 -0
  298. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/gateway/review_comment_gateway.py +0 -0
  299. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/gateway/review_dry_run_comment_gateway.py +0 -0
  300. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/gateway/review_llm_gateway.py +0 -0
  301. {xai_review-0.33.0/ai_review/tests/suites/clients → xai_review-0.35.0/ai_review/tests/fixtures/services/review/internal}/__init__.py +0 -0
  302. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/internal/inline.py +0 -0
  303. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/internal/inline_reply.py +0 -0
  304. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/internal/policy.py +0 -0
  305. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/internal/summary.py +0 -0
  306. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/internal/summary_reply.py +0 -0
  307. {xai_review-0.33.0/ai_review/tests/suites/clients/bitbucket → xai_review-0.35.0/ai_review/tests/fixtures/services/review/runner}/__init__.py +0 -0
  308. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/runner/context.py +0 -0
  309. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/runner/inline.py +0 -0
  310. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/runner/inline_reply.py +0 -0
  311. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/runner/summary.py +0 -0
  312. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/review/runner/summary_reply.py +0 -0
  313. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/fixtures/services/vcs.py +0 -0
  314. {xai_review-0.33.0/ai_review/tests/suites/clients/claude → xai_review-0.35.0/ai_review/tests/suites}/__init__.py +0 -0
  315. {xai_review-0.33.0/ai_review/tests/suites/clients/gemini → xai_review-0.35.0/ai_review/tests/suites/cli}/__init__.py +0 -0
  316. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/cli/test_main.py +0 -0
  317. {xai_review-0.33.0/ai_review/tests/suites/clients/gitea → xai_review-0.35.0/ai_review/tests/suites/clients}/__init__.py +0 -0
  318. {xai_review-0.33.0/ai_review/tests/suites/clients/github → xai_review-0.35.0/ai_review/tests/suites/clients/bitbucket}/__init__.py +0 -0
  319. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/bitbucket/test_client.py +0 -0
  320. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/bitbucket/test_tools.py +0 -0
  321. {xai_review-0.33.0/ai_review/tests/suites/clients/gitlab → xai_review-0.35.0/ai_review/tests/suites/clients/claude}/__init__.py +0 -0
  322. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/claude/test_client.py +0 -0
  323. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/claude/test_schema.py +0 -0
  324. {xai_review-0.33.0/ai_review/tests/suites/clients/ollama → xai_review-0.35.0/ai_review/tests/suites/clients/gemini}/__init__.py +0 -0
  325. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/gemini/test_client.py +0 -0
  326. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/gemini/test_schema.py +0 -0
  327. {xai_review-0.33.0/ai_review/tests/suites/clients/openai → xai_review-0.35.0/ai_review/tests/suites/clients/gitea}/__init__.py +0 -0
  328. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/gitea/test_client.py +0 -0
  329. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/gitea/test_tools.py +0 -0
  330. {xai_review-0.33.0/ai_review/tests/suites/libs → xai_review-0.35.0/ai_review/tests/suites/clients/github}/__init__.py +0 -0
  331. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/github/test_client.py +0 -0
  332. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/github/test_tools.py +0 -0
  333. {xai_review-0.33.0/ai_review/tests/suites/libs/asynchronous → xai_review-0.35.0/ai_review/tests/suites/clients/gitlab}/__init__.py +0 -0
  334. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/gitlab/test_client.py +0 -0
  335. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/gitlab/test_tools.py +0 -0
  336. {xai_review-0.33.0/ai_review/tests/suites/libs/config → xai_review-0.35.0/ai_review/tests/suites/clients/ollama}/__init__.py +0 -0
  337. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/ollama/test_client.py +0 -0
  338. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/clients/ollama/test_schema.py +0 -0
  339. {xai_review-0.33.0/ai_review/tests/suites/libs/diff → xai_review-0.35.0/ai_review/tests/suites/clients/openai}/__init__.py +0 -0
  340. {xai_review-0.33.0/ai_review/tests/suites/libs/http → xai_review-0.35.0/ai_review/tests/suites/clients/openai/v1}/__init__.py +0 -0
  341. {xai_review-0.33.0/ai_review/tests/suites/libs/llm → xai_review-0.35.0/ai_review/tests/suites/clients/openai/v2}/__init__.py +0 -0
  342. {xai_review-0.33.0/ai_review/tests/suites/libs/template → xai_review-0.35.0/ai_review/tests/suites/clients/openrouter}/__init__.py +0 -0
  343. {xai_review-0.33.0/ai_review/tests/suites/services → xai_review-0.35.0/ai_review/tests/suites/libs}/__init__.py +0 -0
  344. {xai_review-0.33.0/ai_review/tests/suites/services/artifacts → xai_review-0.35.0/ai_review/tests/suites/libs/asynchronous}/__init__.py +0 -0
  345. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/libs/asynchronous/test_gather.py +0 -0
  346. {xai_review-0.33.0/ai_review/tests/suites/services/cost → xai_review-0.35.0/ai_review/tests/suites/libs/config}/__init__.py +0 -0
  347. {xai_review-0.33.0/ai_review/tests/suites/services/diff → xai_review-0.35.0/ai_review/tests/suites/libs/config/llm}/__init__.py +0 -0
  348. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/libs/config/test_prompt.py +0 -0
  349. {xai_review-0.33.0/ai_review/tests/suites/services/hook → xai_review-0.35.0/ai_review/tests/suites/libs/diff}/__init__.py +0 -0
  350. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/libs/diff/test_models.py +0 -0
  351. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/libs/diff/test_parser.py +0 -0
  352. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/libs/diff/test_tools.py +0 -0
  353. {xai_review-0.33.0/ai_review/tests/suites/services/llm → xai_review-0.35.0/ai_review/tests/suites/libs/http}/__init__.py +0 -0
  354. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/libs/http/test_paginate.py +0 -0
  355. {xai_review-0.33.0/ai_review/tests/suites/services/llm/claude → xai_review-0.35.0/ai_review/tests/suites/libs/llm}/__init__.py +0 -0
  356. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/libs/llm/test_output_json_parser.py +0 -0
  357. {xai_review-0.33.0/ai_review/tests/suites/services/llm/gemini → xai_review-0.35.0/ai_review/tests/suites/libs/template}/__init__.py +0 -0
  358. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/libs/template/test_render.py +0 -0
  359. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/libs/test_json.py +0 -0
  360. {xai_review-0.33.0/ai_review/tests/suites/services/llm/ollama → xai_review-0.35.0/ai_review/tests/suites/services}/__init__.py +0 -0
  361. {xai_review-0.33.0/ai_review/tests/suites/services/llm/openai → xai_review-0.35.0/ai_review/tests/suites/services/artifacts}/__init__.py +0 -0
  362. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/artifacts/test_service.py +0 -0
  363. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/artifacts/test_tools.py +0 -0
  364. {xai_review-0.33.0/ai_review/tests/suites/services/prompt → xai_review-0.35.0/ai_review/tests/suites/services/cost}/__init__.py +0 -0
  365. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/cost/test_schema.py +0 -0
  366. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/cost/test_service.py +0 -0
  367. {xai_review-0.33.0/ai_review/tests/suites/services/review → xai_review-0.35.0/ai_review/tests/suites/services/diff}/__init__.py +0 -0
  368. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/diff/test_renderers.py +0 -0
  369. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/diff/test_service.py +0 -0
  370. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/diff/test_tools.py +0 -0
  371. {xai_review-0.33.0/ai_review/tests/suites/services/review/gateway → xai_review-0.35.0/ai_review/tests/suites/services/hook}/__init__.py +0 -0
  372. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/hook/test_service.py +0 -0
  373. {xai_review-0.33.0/ai_review/tests/suites/services/review/internal → xai_review-0.35.0/ai_review/tests/suites/services/llm}/__init__.py +0 -0
  374. {xai_review-0.33.0/ai_review/tests/suites/services/review/internal/inline → xai_review-0.35.0/ai_review/tests/suites/services/llm/claude}/__init__.py +0 -0
  375. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/llm/claude/test_client.py +0 -0
  376. {xai_review-0.33.0/ai_review/tests/suites/services/review/internal/inline_reply → xai_review-0.35.0/ai_review/tests/suites/services/llm/gemini}/__init__.py +0 -0
  377. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/llm/gemini/test_client.py +0 -0
  378. {xai_review-0.33.0/ai_review/tests/suites/services/review/internal/policy → xai_review-0.35.0/ai_review/tests/suites/services/llm/ollama}/__init__.py +0 -0
  379. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/llm/ollama/test_client.py +0 -0
  380. {xai_review-0.33.0/ai_review/tests/suites/services/review/internal/summary → xai_review-0.35.0/ai_review/tests/suites/services/llm/openai}/__init__.py +0 -0
  381. {xai_review-0.33.0/ai_review/tests/suites/services/review/internal/summary_reply → xai_review-0.35.0/ai_review/tests/suites/services/llm/openrouter}/__init__.py +0 -0
  382. {xai_review-0.33.0/ai_review/tests/suites/services/review/runner → xai_review-0.35.0/ai_review/tests/suites/services/prompt}/__init__.py +0 -0
  383. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/prompt/test_adapter.py +0 -0
  384. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/prompt/test_schema.py +0 -0
  385. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/prompt/test_service.py +0 -0
  386. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/prompt/test_tools.py +0 -0
  387. {xai_review-0.33.0/ai_review/tests/suites/services/vcs → xai_review-0.35.0/ai_review/tests/suites/services/review}/__init__.py +0 -0
  388. {xai_review-0.33.0/ai_review/tests/suites/services/vcs/bitbucket → xai_review-0.35.0/ai_review/tests/suites/services/review/gateway}/__init__.py +0 -0
  389. {xai_review-0.33.0/ai_review/tests/suites/services/vcs/gitea → xai_review-0.35.0/ai_review/tests/suites/services/review/internal}/__init__.py +0 -0
  390. {xai_review-0.33.0/ai_review/tests/suites/services/vcs/github → xai_review-0.35.0/ai_review/tests/suites/services/review/internal/inline}/__init__.py +0 -0
  391. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/internal/inline/test_schema.py +0 -0
  392. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/internal/inline/test_service.py +0 -0
  393. {xai_review-0.33.0/ai_review/tests/suites/services/vcs/gitlab → xai_review-0.35.0/ai_review/tests/suites/services/review/internal/inline_reply}/__init__.py +0 -0
  394. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/internal/inline_reply/test_schema.py +0 -0
  395. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/internal/inline_reply/test_service.py +0 -0
  396. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/internal/policy/test_service.py +0 -0
  397. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/internal/summary/test_schema.py +0 -0
  398. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/internal/summary/test_service.py +0 -0
  399. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/internal/summary_reply/test_schema.py +0 -0
  400. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/internal/summary_reply/test_service.py +0 -0
  401. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/runner/test_context.py +0 -0
  402. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/runner/test_inline.py +0 -0
  403. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/runner/test_inline_reply.py +0 -0
  404. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/runner/test_summary.py +0 -0
  405. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/review/runner/test_summary_reply.py +0 -0
  406. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/vcs/bitbucket/test_adapter.py +0 -0
  407. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/vcs/bitbucket/test_client.py +0 -0
  408. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/vcs/gitea/test_adapter.py +0 -0
  409. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/vcs/gitea/test_client.py +0 -0
  410. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/vcs/github/test_adapter.py +0 -0
  411. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/vcs/github/test_client.py +0 -0
  412. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/vcs/gitlab/test_adapter.py +0 -0
  413. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/vcs/gitlab/test_client.py +0 -0
  414. {xai_review-0.33.0 → xai_review-0.35.0}/ai_review/tests/suites/services/vcs/test_factory.py +0 -0
  415. {xai_review-0.33.0 → xai_review-0.35.0}/setup.cfg +0 -0
  416. {xai_review-0.33.0 → xai_review-0.35.0}/xai_review.egg-info/dependency_links.txt +0 -0
  417. {xai_review-0.33.0 → xai_review-0.35.0}/xai_review.egg-info/entry_points.txt +0 -0
  418. {xai_review-0.33.0 → xai_review-0.35.0}/xai_review.egg-info/requires.txt +0 -0
  419. {xai_review-0.33.0 → xai_review-0.35.0}/xai_review.egg-info/top_level.txt +0 -0
@@ -1,14 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xai-review
3
- Version: 0.33.0
4
- Summary: AI-powered code review tool
3
+ Version: 0.35.0
4
+ Summary: AI-powered code review tool for GitHub, GitLab, Bitbucket and Gitea — built with LLMs like OpenAI, Claude, Gemini, Ollama, and OpenRouter
5
5
  Author-email: Nikita Filonov <nikita.filonov@example.com>
6
6
  Maintainer-email: Nikita Filonov <nikita.filonov@example.com>
7
7
  License: Apache-2.0
8
8
  Project-URL: Issues, https://github.com/Nikita-Filonov/ai-review/issues
9
9
  Project-URL: Homepage, https://github.com/Nikita-Filonov/ai-review
10
10
  Project-URL: Repository, https://github.com/Nikita-Filonov/ai-review
11
- Keywords: ai,code review,llm,openai,claude,gemini
11
+ Keywords: ai,code review,llm,openai,claude,gemini,ollama,openrouter,ci/cd,gitlab,github,gitea,bitbucket
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
@@ -66,7 +66,8 @@ improve code quality, enforce consistency, and speed up the review process.
66
66
 
67
67
  ✨ Key features:
68
68
 
69
- - **Multiple LLM providers** — choose between **OpenAI**, **Claude**, **Gemini**, or **Ollama**, and switch anytime.
69
+ - **Multiple LLM providers** — choose between **OpenAI**, **Claude**, **Gemini**, **Ollama**, or **OpenRouter**, and
70
+ switch anytime.
70
71
  - **VCS integration** — works out of the box with **GitLab**, **GitHub**, **Bitbucket**, and **Gitea**.
71
72
  - **Customizable prompts** — adapt inline, context, and summary reviews to match your team’s coding guidelines.
72
73
  - **Reply modes** — AI can now **participate in existing review threads**, adding follow-up replies in both inline and
@@ -120,7 +121,7 @@ pip install xai-review
120
121
  Or run directly via Docker:
121
122
 
122
123
  ```bash
123
- docker run --rm -v $(pwd):/app nikitafilonov/ai-review:latest run-summary
124
+ docker run --rm -v $(pwd):/app nikitafilonov/ai-review:latest ai-review run-summary
124
125
  ```
125
126
 
126
127
  🐳 Pull from [DockerHub](https://hub.docker.com/r/nikitafilonov/ai-review)
@@ -146,8 +147,8 @@ vcs:
146
147
  provider: GITLAB
147
148
 
148
149
  pipeline:
149
- project_id: 1
150
- merge_request_id: 100
150
+ project_id: "1"
151
+ merge_request_id: "100"
151
152
 
152
153
  http_client:
153
154
  timeout: 120
@@ -176,7 +177,7 @@ for complete, ready-to-use examples.
176
177
 
177
178
  Key things you can customize:
178
179
 
179
- - **LLM provider** — OpenAI, Gemini, Claude, or Ollama
180
+ - **LLM provider** — OpenAI, Gemini, Claude, Ollama, or OpenRouter
180
181
  - **Model settings** — model name, temperature, max tokens
181
182
  - **VCS integration** — works out of the box with **GitLab**, **GitHub**, **Bitbucket**, and **Gitea**
182
183
  - **Review policy** — which files to include/exclude, review modes
@@ -220,7 +221,7 @@ jobs:
220
221
  with:
221
222
  fetch-depth: 0
222
223
 
223
- - uses: Nikita-Filonov/ai-review@v0.33.0
224
+ - uses: Nikita-Filonov/ai-review@v0.35.0
224
225
  with:
225
226
  review-command: ${{ inputs.review-command }}
226
227
  env:
@@ -298,7 +299,7 @@ AI Review does **not store**, **log**, or **transmit** your source code to any e
298
299
  provider** explicitly configured in your `.ai-review.yaml`.
299
300
 
300
301
  All data is sent **directly** from your CI/CD environment to the selected LLM API endpoint (e.g. OpenAI, Gemini,
301
- Claude). No intermediary servers or storage layers are involved.
302
+ Claude, OpenRouter). No intermediary servers or storage layers are involved.
302
303
 
303
304
  If you use **Ollama**, requests are sent to your **local or self-hosted Ollama runtime**
304
305
  (by default `http://localhost:11434`). This allows you to run reviews completely **offline**, keeping all data strictly
@@ -32,7 +32,8 @@ improve code quality, enforce consistency, and speed up the review process.
32
32
 
33
33
  ✨ Key features:
34
34
 
35
- - **Multiple LLM providers** — choose between **OpenAI**, **Claude**, **Gemini**, or **Ollama**, and switch anytime.
35
+ - **Multiple LLM providers** — choose between **OpenAI**, **Claude**, **Gemini**, **Ollama**, or **OpenRouter**, and
36
+ switch anytime.
36
37
  - **VCS integration** — works out of the box with **GitLab**, **GitHub**, **Bitbucket**, and **Gitea**.
37
38
  - **Customizable prompts** — adapt inline, context, and summary reviews to match your team’s coding guidelines.
38
39
  - **Reply modes** — AI can now **participate in existing review threads**, adding follow-up replies in both inline and
@@ -86,7 +87,7 @@ pip install xai-review
86
87
  Or run directly via Docker:
87
88
 
88
89
  ```bash
89
- docker run --rm -v $(pwd):/app nikitafilonov/ai-review:latest run-summary
90
+ docker run --rm -v $(pwd):/app nikitafilonov/ai-review:latest ai-review run-summary
90
91
  ```
91
92
 
92
93
  🐳 Pull from [DockerHub](https://hub.docker.com/r/nikitafilonov/ai-review)
@@ -112,8 +113,8 @@ vcs:
112
113
  provider: GITLAB
113
114
 
114
115
  pipeline:
115
- project_id: 1
116
- merge_request_id: 100
116
+ project_id: "1"
117
+ merge_request_id: "100"
117
118
 
118
119
  http_client:
119
120
  timeout: 120
@@ -142,7 +143,7 @@ for complete, ready-to-use examples.
142
143
 
143
144
  Key things you can customize:
144
145
 
145
- - **LLM provider** — OpenAI, Gemini, Claude, or Ollama
146
+ - **LLM provider** — OpenAI, Gemini, Claude, Ollama, or OpenRouter
146
147
  - **Model settings** — model name, temperature, max tokens
147
148
  - **VCS integration** — works out of the box with **GitLab**, **GitHub**, **Bitbucket**, and **Gitea**
148
149
  - **Review policy** — which files to include/exclude, review modes
@@ -186,7 +187,7 @@ jobs:
186
187
  with:
187
188
  fetch-depth: 0
188
189
 
189
- - uses: Nikita-Filonov/ai-review@v0.33.0
190
+ - uses: Nikita-Filonov/ai-review@v0.35.0
190
191
  with:
191
192
  review-command: ${{ inputs.review-command }}
192
193
  env:
@@ -264,7 +265,7 @@ AI Review does **not store**, **log**, or **transmit** your source code to any e
264
265
  provider** explicitly configured in your `.ai-review.yaml`.
265
266
 
266
267
  All data is sent **directly** from your CI/CD environment to the selected LLM API endpoint (e.g. OpenAI, Gemini,
267
- Claude). No intermediary servers or storage layers are involved.
268
+ Claude, OpenRouter). No intermediary servers or storage layers are involved.
268
269
 
269
270
  If you use **Ollama**, requests are sent to your **local or self-hosted Ollama runtime**
270
271
  (by default `http://localhost:11434`). This allows you to run reviews completely **offline**, keeping all data strictly
@@ -17,7 +17,7 @@ class ClaudeHTTPClientError(HTTPClientError):
17
17
  class ClaudeHTTPClient(HTTPClient, ClaudeHTTPClientProtocol):
18
18
  @handle_http_error(client="ClaudeHTTPClient", exception=ClaudeHTTPClientError)
19
19
  async def chat_api(self, request: ClaudeChatRequestSchema) -> Response:
20
- return await self.post("/v1/messages", json=request.model_dump())
20
+ return await self.post("/v1/messages", json=request.model_dump(exclude_none=True))
21
21
 
22
22
  async def chat(self, request: ClaudeChatRequestSchema) -> ClaudeChatResponseSchema:
23
23
  response = await self.chat_api(request)
@@ -12,8 +12,8 @@ class ClaudeChatRequestSchema(BaseModel):
12
12
  model: str
13
13
  system: str | None = None
14
14
  messages: list[ClaudeMessageSchema]
15
- max_tokens: int
16
- temperature: float
15
+ max_tokens: int | None = None
16
+ temperature: float | None = None
17
17
 
18
18
 
19
19
  class ClaudeContentSchema(BaseModel):
@@ -19,7 +19,8 @@ class GeminiHTTPClient(HTTPClient, GeminiHTTPClientProtocol):
19
19
  async def chat_api(self, request: GeminiChatRequestSchema) -> Response:
20
20
  meta = settings.llm.meta
21
21
  return await self.post(
22
- f"/v1beta/models/{meta.model}:generateContent", json=request.model_dump()
22
+ f"/v1beta/models/{meta.model}:generateContent",
23
+ json=request.model_dump(exclude_none=True)
23
24
  )
24
25
 
25
26
  async def chat(self, request: GeminiChatRequestSchema) -> GeminiChatResponseSchema:
@@ -45,8 +45,8 @@ class GeminiCandidateSchema(BaseModel):
45
45
  class GeminiGenerationConfigSchema(BaseModel):
46
46
  model_config = ConfigDict(populate_by_name=True)
47
47
 
48
- temperature: float
49
- max_output_tokens: int = Field(alias="maxOutputTokens")
48
+ temperature: float | None = None
49
+ max_output_tokens: int | None = Field(alias="maxOutputTokens", default=None)
50
50
 
51
51
 
52
52
  class GeminiChatRequestSchema(BaseModel):
@@ -17,7 +17,7 @@ class OllamaHTTPClientError(HTTPClientError):
17
17
  class OllamaHTTPClient(HTTPClient, OllamaHTTPClientProtocol):
18
18
  @handle_http_error(client="OllamaHTTPClient", exception=OllamaHTTPClientError)
19
19
  async def chat_api(self, request: OllamaChatRequestSchema) -> Response:
20
- return await self.post("/api/chat", json=request.model_dump())
20
+ return await self.post("/api/chat", json=request.model_dump(exclude_none=True))
21
21
 
22
22
  async def chat(self, request: OllamaChatRequestSchema) -> OllamaChatResponseSchema:
23
23
  response = await self.chat_api(request)
@@ -1,7 +1,7 @@
1
1
  from httpx import Response, AsyncHTTPTransport, AsyncClient
2
2
 
3
- from ai_review.clients.openai.schema import OpenAIChatRequestSchema, OpenAIChatResponseSchema
4
- from ai_review.clients.openai.types import OpenAIHTTPClientProtocol
3
+ from ai_review.clients.openai.v1.schema import OpenAIChatRequestSchema, OpenAIChatResponseSchema
4
+ from ai_review.clients.openai.v1.types import OpenAIV1HTTPClientProtocol
5
5
  from ai_review.config import settings
6
6
  from ai_review.libs.http.client import HTTPClient
7
7
  from ai_review.libs.http.event_hooks.logger import LoggerEventHook
@@ -10,22 +10,22 @@ from ai_review.libs.http.transports.retry import RetryTransport
10
10
  from ai_review.libs.logger import get_logger
11
11
 
12
12
 
13
- class OpenAIHTTPClientError(HTTPClientError):
13
+ class OpenAIV1HTTPClientError(HTTPClientError):
14
14
  pass
15
15
 
16
16
 
17
- class OpenAIHTTPClient(HTTPClient, OpenAIHTTPClientProtocol):
18
- @handle_http_error(client='OpenAIHTTPClient', exception=OpenAIHTTPClientError)
17
+ class OpenAIV1HTTPClient(HTTPClient, OpenAIV1HTTPClientProtocol):
18
+ @handle_http_error(client='OpenAIV1HTTPClient', exception=OpenAIV1HTTPClientError)
19
19
  async def chat_api(self, request: OpenAIChatRequestSchema) -> Response:
20
- return await self.post("/chat/completions", json=request.model_dump())
20
+ return await self.post("/chat/completions", json=request.model_dump(exclude_none=True))
21
21
 
22
22
  async def chat(self, request: OpenAIChatRequestSchema) -> OpenAIChatResponseSchema:
23
23
  response = await self.chat_api(request)
24
24
  return OpenAIChatResponseSchema.model_validate_json(response.text)
25
25
 
26
26
 
27
- def get_openai_http_client() -> OpenAIHTTPClient:
28
- logger = get_logger("OPENAI_HTTP_CLIENT")
27
+ def get_openai_v1_http_client() -> OpenAIV1HTTPClient:
28
+ logger = get_logger("OPENAI_V1_HTTP_CLIENT")
29
29
  logger_event_hook = LoggerEventHook(logger=logger)
30
30
  retry_transport = RetryTransport(logger=logger, transport=AsyncHTTPTransport())
31
31
 
@@ -40,4 +40,4 @@ def get_openai_http_client() -> OpenAIHTTPClient:
40
40
  }
41
41
  )
42
42
 
43
- return OpenAIHTTPClient(client=client)
43
+ return OpenAIV1HTTPClient(client=client)
@@ -21,7 +21,7 @@ class OpenAIChoiceSchema(BaseModel):
21
21
  class OpenAIChatRequestSchema(BaseModel):
22
22
  model: str
23
23
  messages: list[OpenAIMessageSchema]
24
- max_tokens: int
24
+ max_tokens: int | None = None
25
25
  temperature: float
26
26
 
27
27
 
@@ -0,0 +1,8 @@
1
+ from typing import Protocol
2
+
3
+ from ai_review.clients.openai.v1.schema import OpenAIChatRequestSchema, OpenAIChatResponseSchema
4
+
5
+
6
+ class OpenAIV1HTTPClientProtocol(Protocol):
7
+ async def chat(self, request: OpenAIChatRequestSchema) -> OpenAIChatResponseSchema:
8
+ ...
@@ -0,0 +1,46 @@
1
+ from httpx import Response, AsyncClient, AsyncHTTPTransport
2
+
3
+ from ai_review.clients.openai.v2.schema import (
4
+ OpenAIResponsesRequestSchema,
5
+ OpenAIResponsesResponseSchema
6
+ )
7
+ from ai_review.clients.openai.v2.types import OpenAIV2HTTPClientProtocol
8
+ from ai_review.config import settings
9
+ from ai_review.libs.http.client import HTTPClient
10
+ from ai_review.libs.http.event_hooks.logger import LoggerEventHook
11
+ from ai_review.libs.http.handlers import HTTPClientError, handle_http_error
12
+ from ai_review.libs.http.transports.retry import RetryTransport
13
+ from ai_review.libs.logger import get_logger
14
+
15
+
16
+ class OpenAIV2HTTPClientError(HTTPClientError):
17
+ pass
18
+
19
+
20
+ class OpenAIV2HTTPClient(HTTPClient, OpenAIV2HTTPClientProtocol):
21
+ @handle_http_error(client='OpenAIV2HTTPClient', exception=OpenAIV2HTTPClientError)
22
+ async def chat_api(self, request: OpenAIResponsesRequestSchema) -> Response:
23
+ return await self.post("/responses", json=request.model_dump(exclude_none=True))
24
+
25
+ async def chat(self, request: OpenAIResponsesRequestSchema) -> OpenAIResponsesResponseSchema:
26
+ response = await self.chat_api(request)
27
+ return OpenAIResponsesResponseSchema.model_validate_json(response.text)
28
+
29
+
30
+ def get_openai_v2_http_client() -> OpenAIV2HTTPClient:
31
+ logger = get_logger("OPENAI_V2_HTTP_CLIENT")
32
+ logger_event_hook = LoggerEventHook(logger=logger)
33
+ retry_transport = RetryTransport(logger=logger, transport=AsyncHTTPTransport())
34
+
35
+ client = AsyncClient(
36
+ timeout=settings.llm.http_client.timeout,
37
+ headers={"Authorization": f"Bearer {settings.llm.http_client.api_token_value}"},
38
+ base_url=settings.llm.http_client.api_url_value,
39
+ transport=retry_transport,
40
+ event_hooks={
41
+ 'request': [logger_event_hook.request],
42
+ 'response': [logger_event_hook.response]
43
+ }
44
+ )
45
+
46
+ return OpenAIV2HTTPClient(client=client)
@@ -0,0 +1,47 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class OpenAIResponseUsageSchema(BaseModel):
5
+ total_tokens: int
6
+ input_tokens: int
7
+ output_tokens: int
8
+
9
+
10
+ class OpenAIInputMessageSchema(BaseModel):
11
+ role: str
12
+ content: str
13
+
14
+
15
+ class OpenAIResponseContentSchema(BaseModel):
16
+ type: str
17
+ text: str | None = None
18
+
19
+
20
+ class OpenAIResponseOutputSchema(BaseModel):
21
+ type: str
22
+ role: str | None = None
23
+ content: list[OpenAIResponseContentSchema] | None = None
24
+
25
+
26
+ class OpenAIResponsesRequestSchema(BaseModel):
27
+ model: str
28
+ input: list[OpenAIInputMessageSchema]
29
+ temperature: float | None = None
30
+ instructions: str | None = None
31
+ max_output_tokens: int | None = None
32
+
33
+
34
+ class OpenAIResponsesResponseSchema(BaseModel):
35
+ usage: OpenAIResponseUsageSchema
36
+ output: list[OpenAIResponseOutputSchema]
37
+
38
+ @property
39
+ def first_text(self) -> str:
40
+ results: list[str] = []
41
+ for block in self.output:
42
+ if block.type == "message" and block.content:
43
+ for content in block.content:
44
+ if content.type == "output_text" and content.text:
45
+ results.append(content.text)
46
+
47
+ return "".join(results).strip()
@@ -0,0 +1,11 @@
1
+ from typing import Protocol
2
+
3
+ from ai_review.clients.openai.v2.schema import (
4
+ OpenAIResponsesRequestSchema,
5
+ OpenAIResponsesResponseSchema
6
+ )
7
+
8
+
9
+ class OpenAIV2HTTPClientProtocol(Protocol):
10
+ async def chat(self, request: OpenAIResponsesRequestSchema) -> OpenAIResponsesResponseSchema:
11
+ ...
@@ -0,0 +1,50 @@
1
+ from httpx import AsyncClient, Response, AsyncHTTPTransport
2
+
3
+ from ai_review.clients.openrouter.schema import OpenRouterChatRequestSchema, OpenRouterChatResponseSchema
4
+ from ai_review.clients.openrouter.types import OpenRouterHTTPClientProtocol
5
+ from ai_review.config import settings
6
+ from ai_review.libs.http.client import HTTPClient
7
+ from ai_review.libs.http.event_hooks.logger import LoggerEventHook
8
+ from ai_review.libs.http.handlers import HTTPClientError, handle_http_error
9
+ from ai_review.libs.http.transports.retry import RetryTransport
10
+ from ai_review.libs.logger import get_logger
11
+
12
+
13
+ class OpenRouterHTTPClientError(HTTPClientError):
14
+ pass
15
+
16
+
17
+ class OpenRouterHTTPClient(HTTPClient, OpenRouterHTTPClientProtocol):
18
+ @handle_http_error(client="OpenRouterHTTPClient", exception=OpenRouterHTTPClientError)
19
+ async def chat_api(self, request: OpenRouterChatRequestSchema) -> Response:
20
+ return await self.post("/chat/completions", json=request.model_dump(exclude_none=True))
21
+
22
+ async def chat(self, request: OpenRouterChatRequestSchema) -> OpenRouterChatResponseSchema:
23
+ response = await self.chat_api(request)
24
+ return OpenRouterChatResponseSchema.model_validate_json(response.text)
25
+
26
+
27
+ def get_openrouter_http_client() -> OpenRouterHTTPClient:
28
+ logger = get_logger("OPENROUTER_HTTP_CLIENT")
29
+ logger_event_hook = LoggerEventHook(logger=logger)
30
+ retry_transport = RetryTransport(logger=logger, transport=AsyncHTTPTransport())
31
+
32
+ headers = {"Authorization": f"Bearer {settings.llm.http_client.api_token_value}"}
33
+ if settings.llm.meta.title:
34
+ headers["X-Title"] = settings.llm.meta.title
35
+
36
+ if settings.llm.meta.referer:
37
+ headers["Referer"] = settings.llm.meta.referer
38
+
39
+ client = AsyncClient(
40
+ timeout=settings.llm.http_client.timeout,
41
+ headers=headers,
42
+ base_url=settings.llm.http_client.api_url_value,
43
+ transport=retry_transport,
44
+ event_hooks={
45
+ "request": [logger_event_hook.request],
46
+ "response": [logger_event_hook.response],
47
+ },
48
+ )
49
+
50
+ return OpenRouterHTTPClient(client=client)
@@ -0,0 +1,36 @@
1
+ from typing import Literal
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class OpenRouterUsageSchema(BaseModel):
7
+ total_tokens: int
8
+ prompt_tokens: int
9
+ completion_tokens: int
10
+
11
+
12
+ class OpenRouterMessageSchema(BaseModel):
13
+ role: Literal["system", "user", "assistant"]
14
+ content: str
15
+
16
+
17
+ class OpenRouterChoiceSchema(BaseModel):
18
+ message: OpenRouterMessageSchema
19
+
20
+
21
+ class OpenRouterChatRequestSchema(BaseModel):
22
+ model: str
23
+ messages: list[OpenRouterMessageSchema]
24
+ max_tokens: int | None = None
25
+ temperature: float | None = None
26
+
27
+
28
+ class OpenRouterChatResponseSchema(BaseModel):
29
+ usage: OpenRouterUsageSchema
30
+ choices: list[OpenRouterChoiceSchema]
31
+
32
+ @property
33
+ def first_text(self) -> str:
34
+ if not self.choices:
35
+ return ""
36
+ return (self.choices[0].message.content or "").strip()
@@ -0,0 +1,11 @@
1
+ from typing import Protocol
2
+
3
+ from ai_review.clients.openrouter.schema import (
4
+ OpenRouterChatRequestSchema,
5
+ OpenRouterChatResponseSchema
6
+ )
7
+
8
+
9
+ class OpenRouterHTTPClientProtocol(Protocol):
10
+ async def chat(self, request: OpenRouterChatRequestSchema) -> OpenRouterChatResponseSchema:
11
+ ...
@@ -8,6 +8,7 @@ from ai_review.libs.config.llm.claude import ClaudeHTTPClientConfig, ClaudeMetaC
8
8
  from ai_review.libs.config.llm.gemini import GeminiHTTPClientConfig, GeminiMetaConfig
9
9
  from ai_review.libs.config.llm.ollama import OllamaHTTPClientConfig, OllamaMetaConfig
10
10
  from ai_review.libs.config.llm.openai import OpenAIHTTPClientConfig, OpenAIMetaConfig
11
+ from ai_review.libs.config.llm.openrouter import OpenRouterHTTPClientConfig, OpenRouterMetaConfig
11
12
  from ai_review.libs.constants.llm_provider import LLMProvider
12
13
  from ai_review.libs.resources import load_resource
13
14
 
@@ -62,7 +63,13 @@ class OllamaLLMConfig(LLMConfigBase):
62
63
  http_client: OllamaHTTPClientConfig
63
64
 
64
65
 
66
+ class OpenRouterLLMConfig(LLMConfigBase):
67
+ meta: OpenRouterMetaConfig
68
+ provider: Literal[LLMProvider.OPENROUTER]
69
+ http_client: OpenRouterHTTPClientConfig
70
+
71
+
65
72
  LLMConfig = Annotated[
66
- OpenAILLMConfig | GeminiLLMConfig | ClaudeLLMConfig | OllamaLLMConfig,
73
+ OpenAILLMConfig | GeminiLLMConfig | ClaudeLLMConfig | OllamaLLMConfig | OpenRouterLLMConfig,
67
74
  Field(discriminator="provider")
68
75
  ]
@@ -0,0 +1,7 @@
1
+ from pydantic import BaseModel, Field
2
+
3
+
4
+ class LLMMetaConfig(BaseModel):
5
+ model: str
6
+ max_tokens: int | None = Field(default=None, ge=1)
7
+ temperature: float | None = Field(default=None, ge=0.0, le=2.0)
@@ -5,6 +5,10 @@ from ai_review.libs.config.llm.meta import LLMMetaConfig
5
5
  class OpenAIMetaConfig(LLMMetaConfig):
6
6
  model: str = "gpt-4o-mini"
7
7
 
8
+ @property
9
+ def is_v2_model(self) -> bool:
10
+ return any(self.model.startswith(model) for model in ("gpt-5", "gpt-4.1"))
11
+
8
12
 
9
13
  class OpenAIHTTPClientConfig(HTTPClientWithTokenConfig):
10
14
  pass
@@ -0,0 +1,12 @@
1
+ from ai_review.libs.config.http import HTTPClientWithTokenConfig
2
+ from ai_review.libs.config.llm.meta import LLMMetaConfig
3
+
4
+
5
+ class OpenRouterMetaConfig(LLMMetaConfig):
6
+ model: str = "openai/gpt-4o-mini"
7
+ title: str | None = None
8
+ referer: str | None = None
9
+
10
+
11
+ class OpenRouterHTTPClientConfig(HTTPClientWithTokenConfig):
12
+ pass
@@ -6,3 +6,4 @@ class LLMProvider(StrEnum):
6
6
  GEMINI = "GEMINI"
7
7
  CLAUDE = "CLAUDE"
8
8
  OLLAMA = "OLLAMA"
9
+ OPENROUTER = "OPENROUTER"
@@ -0,0 +1,93 @@
1
+ # ===============================
2
+ # 📊 Pricing per 1 token (USD)
3
+ # ===============================
4
+ # NOTE:
5
+ # - Prices are per 1 token and can change over time.
6
+ # - For the latest OpenAI and Anthropic pricing, see:
7
+ # - https://openai.com/api/pricing
8
+ # - https://www.anthropic.com/pricing
9
+ # - For OpenRouter models, prices vary by provider: https://openrouter.ai
10
+
11
+ # --- OpenAI ---
12
+ gpt-4o-mini:
13
+ input: 0.15e-6
14
+ output: 0.60e-6
15
+
16
+ gpt-4o:
17
+ input: 5.00e-6
18
+ output: 15.00e-6
19
+
20
+ gpt-4.1-mini:
21
+ input: 0.15e-6
22
+ output: 0.60e-6
23
+
24
+ gpt-4.1:
25
+ input: 5.00e-6
26
+ output: 15.00e-6
27
+
28
+ gpt-5:
29
+ input: 10.00e-6
30
+ output: 30.00e-6
31
+
32
+ gpt-3.5-turbo:
33
+ input: 0.50e-6
34
+ output: 1.50e-6
35
+
36
+ # --- Google Gemini ---
37
+ gemini-2.5-flash-lite:
38
+ input: 0.10e-6
39
+ output: 0.40e-6
40
+
41
+ gemini-2.0-flash-lite:
42
+ input: 0.019e-6
43
+ output: 0.10e-6
44
+
45
+ gemini-2.0-pro:
46
+ input: 0.125e-6
47
+ output: 0.375e-6
48
+
49
+ gemini-2.5-pro:
50
+ input: 1.25e-6
51
+ output: 10.00e-6
52
+
53
+ gemini-2.5-pro-long-context:
54
+ input: 2.50e-6
55
+ output: 15.00e-6
56
+
57
+ # --- Anthropic Claude ---
58
+ claude-3.5-sonnet:
59
+ input: 3.00e-6
60
+ output: 15.00e-6
61
+
62
+ claude-3-opus:
63
+ input: 15.00e-6
64
+ output: 75.00e-6
65
+
66
+ claude-3-sonnet:
67
+ input: 3.00e-6
68
+ output: 15.00e-6
69
+
70
+ claude-3-haiku:
71
+ input: 0.25e-6
72
+ output: 1.25e-6
73
+
74
+ # --- OpenRouter ---
75
+ o3-mini:
76
+ input: 1.10e-6
77
+ output: 4.40e-6
78
+
79
+ openai/chatgpt-4o-latest:
80
+ input: 5.00e-6
81
+ output: 15.00e-6
82
+
83
+ mistralai/mixtral-8x7b:
84
+ input: 0.24e-6
85
+ output: 0.48e-6
86
+
87
+ meta-llama/llama-3-8b-instruct:
88
+ input: 0.20e-6
89
+ output: 0.40e-6
90
+
91
+ meta-llama/llama-3-70b-instruct:
92
+ input: 0.80e-6
93
+ output: 1.60e-6
@@ -4,6 +4,7 @@ from ai_review.services.llm.claude.client import ClaudeLLMClient
4
4
  from ai_review.services.llm.gemini.client import GeminiLLMClient
5
5
  from ai_review.services.llm.ollama.client import OllamaLLMClient
6
6
  from ai_review.services.llm.openai.client import OpenAILLMClient
7
+ from ai_review.services.llm.openrouter.client import OpenRouterLLMClient
7
8
  from ai_review.services.llm.types import LLMClientProtocol
8
9
 
9
10
 
@@ -17,5 +18,7 @@ def get_llm_client() -> LLMClientProtocol:
17
18
  return ClaudeLLMClient()
18
19
  case LLMProvider.OLLAMA:
19
20
  return OllamaLLMClient()
21
+ case LLMProvider.OPENROUTER:
22
+ return OpenRouterLLMClient()
20
23
  case _:
21
24
  raise ValueError(f"Unsupported LLM provider: {settings.llm.provider}")