xai-review 0.17.0__tar.gz → 0.19.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.
- {xai_review-0.17.0/xai_review.egg-info → xai_review-0.19.0}/PKG-INFO +42 -5
- xai_review-0.17.0/PKG-INFO → xai_review-0.19.0/README.md +31 -27
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/github/pr/client.py +13 -7
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/github/pr/schema/pull_request.py +6 -6
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/gitlab/mr/client.py +29 -20
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/gitlab/mr/schema/changes.py +5 -5
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/gitlab/mr/schema/discussions.py +1 -4
- xai_review-0.19.0/ai_review/clients/gitlab/mr/schema/notes.py +19 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/llm/factory.py +1 -1
- xai_review-0.19.0/ai_review/services/prompt/adapter.py +25 -0
- xai_review-0.19.0/ai_review/services/prompt/schema.py +52 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/review/service.py +45 -42
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/vcs/factory.py +1 -1
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/vcs/github/client.py +55 -33
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/vcs/gitlab/client.py +62 -44
- xai_review-0.19.0/ai_review/services/vcs/types.py +64 -0
- xai_review-0.19.0/ai_review/tests/suites/services/cost/test_schema.py +124 -0
- xai_review-0.19.0/ai_review/tests/suites/services/cost/test_service.py +99 -0
- xai_review-0.19.0/ai_review/tests/suites/services/prompt/test_adapter.py +59 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/services/prompt/test_schema.py +18 -18
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/services/prompt/test_service.py +13 -11
- xai_review-0.19.0/ai_review/tests/suites/services/review/summary/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/pyproject.toml +15 -3
- xai_review-0.17.0/README.md → xai_review-0.19.0/xai_review.egg-info/PKG-INFO +64 -3
- {xai_review-0.17.0 → xai_review-0.19.0}/xai_review.egg-info/SOURCES.txt +5 -1
- {xai_review-0.17.0 → xai_review-0.19.0}/xai_review.egg-info/requires.txt +3 -1
- xai_review-0.17.0/ai_review/clients/gitlab/mr/schema/comments.py +0 -19
- xai_review-0.17.0/ai_review/services/prompt/adapter.py +0 -25
- xai_review-0.17.0/ai_review/services/prompt/schema.py +0 -52
- xai_review-0.17.0/ai_review/services/vcs/types.py +0 -55
- {xai_review-0.17.0 → xai_review-0.19.0}/LICENSE +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/cli/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/cli/commands/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/cli/commands/run_context_review.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/cli/commands/run_inline_review.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/cli/commands/run_review.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/cli/commands/run_summary_review.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/cli/main.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/claude/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/claude/client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/claude/schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/gemini/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/gemini/client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/gemini/schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/github/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/github/client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/github/pr/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/github/pr/schema/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/github/pr/schema/comments.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/github/pr/schema/files.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/github/pr/schema/reviews.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/gitlab/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/gitlab/client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/gitlab/mr/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/gitlab/mr/schema/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/openai/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/openai/client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/clients/openai/schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/config.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/asynchronous/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/asynchronous/gather.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/artifacts.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/base.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/claude.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/gemini.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/github.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/gitlab.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/http.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/llm.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/logger.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/openai.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/prompt.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/review.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/config/vcs.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/constants/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/constants/llm_provider.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/constants/vcs_provider.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/diff/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/diff/models.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/diff/parser.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/diff/tools.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/http/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/http/client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/http/event_hooks/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/http/event_hooks/base.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/http/event_hooks/logger.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/http/handlers.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/http/transports/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/http/transports/retry.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/json.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/logger.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/resources.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/template/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/libs/template/render.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/prompts/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/prompts/default_context.md +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/prompts/default_inline.md +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/prompts/default_summary.md +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/prompts/default_system_context.md +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/prompts/default_system_inline.md +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/prompts/default_system_summary.md +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/resources/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/resources/pricing.yaml +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/artifacts/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/artifacts/schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/artifacts/service.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/artifacts/tools.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/cost/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/cost/schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/cost/service.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/diff/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/diff/renderers.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/diff/schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/diff/service.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/diff/tools.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/git/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/git/service.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/git/types.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/llm/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/llm/claude/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/llm/claude/client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/llm/gemini/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/llm/gemini/client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/llm/openai/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/llm/openai/client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/llm/types.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/prompt/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/prompt/service.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/prompt/tools.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/review/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/review/inline/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/review/inline/schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/review/inline/service.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/review/policy/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/review/policy/service.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/review/summary/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/review/summary/schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/review/summary/service.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/vcs/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/vcs/github/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/services/vcs/gitlab/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/fixtures/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/fixtures/git.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/claude/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/claude/test_client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/claude/test_schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/gemini/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/gemini/test_client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/gemini/test_schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/github/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/github/test_client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/gitlab/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/gitlab/test_client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/openai/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/openai/test_client.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/clients/openai/test_schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/libs/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/libs/config/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/libs/config/test_prompt.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/libs/diff/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/libs/diff/test_models.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/libs/diff/test_parser.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/libs/diff/test_tools.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/libs/template/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/libs/template/test_render.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/libs/test_json.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/services/__init__.py +0 -0
- {xai_review-0.17.0/ai_review/tests/suites/services/diff → xai_review-0.19.0/ai_review/tests/suites/services/cost}/__init__.py +0 -0
- {xai_review-0.17.0/ai_review/tests/suites/services/prompt → xai_review-0.19.0/ai_review/tests/suites/services/diff}/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/services/diff/test_renderers.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/services/diff/test_service.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/services/diff/test_tools.py +0 -0
- {xai_review-0.17.0/ai_review/tests/suites/services/review → xai_review-0.19.0/ai_review/tests/suites/services/prompt}/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/services/prompt/test_tools.py +0 -0
- {xai_review-0.17.0/ai_review/tests/suites/services/review/inline → xai_review-0.19.0/ai_review/tests/suites/services/review}/__init__.py +0 -0
- {xai_review-0.17.0/ai_review/tests/suites/services/review/policy → xai_review-0.19.0/ai_review/tests/suites/services/review/inline}/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/services/review/inline/test_schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/services/review/inline/test_service.py +0 -0
- {xai_review-0.17.0/ai_review/tests/suites/services/review/summary → xai_review-0.19.0/ai_review/tests/suites/services/review/policy}/__init__.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/services/review/policy/test_service.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/services/review/summary/test_schema.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/ai_review/tests/suites/services/review/summary/test_service.py +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/setup.cfg +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/xai_review.egg-info/dependency_links.txt +0 -0
- {xai_review-0.17.0 → xai_review-0.19.0}/xai_review.egg-info/entry_points.txt +0 -0
- {xai_review-0.17.0 → xai_review-0.19.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.
|
|
3
|
+
Version: 0.19.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>
|
|
@@ -9,17 +9,26 @@ 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
11
|
Keywords: ai,code review,llm,openai,claude,gemini
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
17
|
+
Classifier: Topic :: Software Development :: Testing
|
|
18
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
12
20
|
Requires-Python: >=3.11
|
|
13
21
|
Description-Content-Type: text/markdown
|
|
14
22
|
License-File: LICENSE
|
|
15
23
|
Requires-Dist: typer
|
|
16
24
|
Requires-Dist: httpx
|
|
17
25
|
Requires-Dist: pyyaml
|
|
18
|
-
Requires-Dist: pytest
|
|
19
26
|
Requires-Dist: loguru
|
|
20
27
|
Requires-Dist: aiofiles
|
|
21
28
|
Requires-Dist: pydantic
|
|
22
29
|
Requires-Dist: pydantic-settings
|
|
30
|
+
Provides-Extra: test
|
|
31
|
+
Requires-Dist: pytest; extra == "test"
|
|
23
32
|
Dynamic: license-file
|
|
24
33
|
|
|
25
34
|
# AI Review
|
|
@@ -39,6 +48,7 @@ _Made with ❤️ by [@NikitaFilonov](https://t.me/sound_right)_
|
|
|
39
48
|
## 📑 Table of Contents
|
|
40
49
|
|
|
41
50
|
- ✨ [About](#-about)
|
|
51
|
+
- 🧪 [Live Preview](#-live-preview)
|
|
42
52
|
- 🚀 [Quick Start](#-quick-start)
|
|
43
53
|
- ⚙️ [️CI/CD Integration](#-cicd-integration)
|
|
44
54
|
- 🚀 [GitHub Actions](#-github-actions)
|
|
@@ -67,6 +77,27 @@ final decision to human reviewers.
|
|
|
67
77
|
|
|
68
78
|
---
|
|
69
79
|
|
|
80
|
+
## 🧪 Live Preview
|
|
81
|
+
|
|
82
|
+
Curious how **AI Review** works in practice? Here are three real Pull Requests reviewed entirely by the tool — one per
|
|
83
|
+
mode:
|
|
84
|
+
|
|
85
|
+
| Mode | Description | Live Example |
|
|
86
|
+
|------------|----------------------------------------------------|-------------------------------------------------------------------------------|
|
|
87
|
+
| 🧩 Inline | Adds line-by-line comments directly in the diff | [Try AI Review (inline)](https://github.com/Nikita-Filonov/ai-review/pull/4) |
|
|
88
|
+
| 🧠 Context | Performs broader analysis across multiple files | [Try AI Review (context)](https://github.com/Nikita-Filonov/ai-review/pull/5) |
|
|
89
|
+
| 📄 Summary | Posts a concise summary review with key highlights | [Try AI Review (summary)](https://github.com/Nikita-Filonov/ai-review/pull/6) |
|
|
90
|
+
|
|
91
|
+
👉 Each review was generated automatically via GitHub Actions using the corresponding mode:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
ai-review run-inline
|
|
95
|
+
ai-review run-summary
|
|
96
|
+
ai-review run-context
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
70
101
|
## 🚀 Quick Start
|
|
71
102
|
|
|
72
103
|
Install via **pip**:
|
|
@@ -75,12 +106,18 @@ Install via **pip**:
|
|
|
75
106
|
pip install xai-review
|
|
76
107
|
```
|
|
77
108
|
|
|
109
|
+
📦 Available on [PyPI](https://pypi.org/project/xai-review/)
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
78
113
|
Or run directly via Docker:
|
|
79
114
|
|
|
80
115
|
```bash
|
|
81
116
|
docker run --rm -v $(pwd):/app nikitafilonov/ai-review:latest run-summary
|
|
82
117
|
```
|
|
83
118
|
|
|
119
|
+
🐳 Pull from [DockerHub](https://hub.docker.com/r/nikitafilonov/ai-review)
|
|
120
|
+
|
|
84
121
|
👉 Before running, create a basic configuration file [.ai-review.yaml](./docs/configs/.ai-review.yaml) in the root of
|
|
85
122
|
your project:
|
|
86
123
|
|
|
@@ -120,8 +157,8 @@ vcs:
|
|
|
120
157
|
> **Note:** Running `ai-review run` executes the full review (inline + summary).
|
|
121
158
|
> To run only one mode, use the dedicated subcommands:
|
|
122
159
|
> - ai-review run-inline
|
|
123
|
-
> - ai-review run-summary
|
|
124
160
|
> - ai-review run-context
|
|
161
|
+
> - ai-review run-summary
|
|
125
162
|
|
|
126
163
|
---
|
|
127
164
|
|
|
@@ -132,7 +169,7 @@ Key things you can customize:
|
|
|
132
169
|
|
|
133
170
|
- **LLM provider** — OpenAI, Gemini, or Claude
|
|
134
171
|
- **Model settings** — model name, temperature, max tokens
|
|
135
|
-
- **VCS integration** —
|
|
172
|
+
- **VCS integration** — works out of the box with **GitLab** and **GitHub**.
|
|
136
173
|
- **Review policy** — which files to include/exclude, review modes
|
|
137
174
|
- **Prompts** — inline/context/summary prompt templates
|
|
138
175
|
|
|
@@ -170,7 +207,7 @@ jobs:
|
|
|
170
207
|
runs-on: ubuntu-latest
|
|
171
208
|
steps:
|
|
172
209
|
- uses: actions/checkout@v4
|
|
173
|
-
- uses: Nikita-Filonov/ai-review@v0.
|
|
210
|
+
- uses: Nikita-Filonov/ai-review@v0.19.0
|
|
174
211
|
with:
|
|
175
212
|
review-command: ${{ inputs.review-command }}
|
|
176
213
|
env:
|
|
@@ -1,27 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: xai-review
|
|
3
|
-
Version: 0.17.0
|
|
4
|
-
Summary: AI-powered code review tool
|
|
5
|
-
Author-email: Nikita Filonov <nikita.filonov@example.com>
|
|
6
|
-
Maintainer-email: Nikita Filonov <nikita.filonov@example.com>
|
|
7
|
-
License: Apache-2.0
|
|
8
|
-
Project-URL: Issues, https://github.com/Nikita-Filonov/ai-review/issues
|
|
9
|
-
Project-URL: Homepage, https://github.com/Nikita-Filonov/ai-review
|
|
10
|
-
Project-URL: Repository, https://github.com/Nikita-Filonov/ai-review
|
|
11
|
-
Keywords: ai,code review,llm,openai,claude,gemini
|
|
12
|
-
Requires-Python: >=3.11
|
|
13
|
-
Description-Content-Type: text/markdown
|
|
14
|
-
License-File: LICENSE
|
|
15
|
-
Requires-Dist: typer
|
|
16
|
-
Requires-Dist: httpx
|
|
17
|
-
Requires-Dist: pyyaml
|
|
18
|
-
Requires-Dist: pytest
|
|
19
|
-
Requires-Dist: loguru
|
|
20
|
-
Requires-Dist: aiofiles
|
|
21
|
-
Requires-Dist: pydantic
|
|
22
|
-
Requires-Dist: pydantic-settings
|
|
23
|
-
Dynamic: license-file
|
|
24
|
-
|
|
25
1
|
# AI Review
|
|
26
2
|
|
|
27
3
|
AI-powered code review tool.
|
|
@@ -39,6 +15,7 @@ _Made with ❤️ by [@NikitaFilonov](https://t.me/sound_right)_
|
|
|
39
15
|
## 📑 Table of Contents
|
|
40
16
|
|
|
41
17
|
- ✨ [About](#-about)
|
|
18
|
+
- 🧪 [Live Preview](#-live-preview)
|
|
42
19
|
- 🚀 [Quick Start](#-quick-start)
|
|
43
20
|
- ⚙️ [️CI/CD Integration](#-cicd-integration)
|
|
44
21
|
- 🚀 [GitHub Actions](#-github-actions)
|
|
@@ -67,6 +44,27 @@ final decision to human reviewers.
|
|
|
67
44
|
|
|
68
45
|
---
|
|
69
46
|
|
|
47
|
+
## 🧪 Live Preview
|
|
48
|
+
|
|
49
|
+
Curious how **AI Review** works in practice? Here are three real Pull Requests reviewed entirely by the tool — one per
|
|
50
|
+
mode:
|
|
51
|
+
|
|
52
|
+
| Mode | Description | Live Example |
|
|
53
|
+
|------------|----------------------------------------------------|-------------------------------------------------------------------------------|
|
|
54
|
+
| 🧩 Inline | Adds line-by-line comments directly in the diff | [Try AI Review (inline)](https://github.com/Nikita-Filonov/ai-review/pull/4) |
|
|
55
|
+
| 🧠 Context | Performs broader analysis across multiple files | [Try AI Review (context)](https://github.com/Nikita-Filonov/ai-review/pull/5) |
|
|
56
|
+
| 📄 Summary | Posts a concise summary review with key highlights | [Try AI Review (summary)](https://github.com/Nikita-Filonov/ai-review/pull/6) |
|
|
57
|
+
|
|
58
|
+
👉 Each review was generated automatically via GitHub Actions using the corresponding mode:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
ai-review run-inline
|
|
62
|
+
ai-review run-summary
|
|
63
|
+
ai-review run-context
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
70
68
|
## 🚀 Quick Start
|
|
71
69
|
|
|
72
70
|
Install via **pip**:
|
|
@@ -75,12 +73,18 @@ Install via **pip**:
|
|
|
75
73
|
pip install xai-review
|
|
76
74
|
```
|
|
77
75
|
|
|
76
|
+
📦 Available on [PyPI](https://pypi.org/project/xai-review/)
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
78
80
|
Or run directly via Docker:
|
|
79
81
|
|
|
80
82
|
```bash
|
|
81
83
|
docker run --rm -v $(pwd):/app nikitafilonov/ai-review:latest run-summary
|
|
82
84
|
```
|
|
83
85
|
|
|
86
|
+
🐳 Pull from [DockerHub](https://hub.docker.com/r/nikitafilonov/ai-review)
|
|
87
|
+
|
|
84
88
|
👉 Before running, create a basic configuration file [.ai-review.yaml](./docs/configs/.ai-review.yaml) in the root of
|
|
85
89
|
your project:
|
|
86
90
|
|
|
@@ -120,8 +124,8 @@ vcs:
|
|
|
120
124
|
> **Note:** Running `ai-review run` executes the full review (inline + summary).
|
|
121
125
|
> To run only one mode, use the dedicated subcommands:
|
|
122
126
|
> - ai-review run-inline
|
|
123
|
-
> - ai-review run-summary
|
|
124
127
|
> - ai-review run-context
|
|
128
|
+
> - ai-review run-summary
|
|
125
129
|
|
|
126
130
|
---
|
|
127
131
|
|
|
@@ -132,7 +136,7 @@ Key things you can customize:
|
|
|
132
136
|
|
|
133
137
|
- **LLM provider** — OpenAI, Gemini, or Claude
|
|
134
138
|
- **Model settings** — model name, temperature, max tokens
|
|
135
|
-
- **VCS integration** —
|
|
139
|
+
- **VCS integration** — works out of the box with **GitLab** and **GitHub**.
|
|
136
140
|
- **Review policy** — which files to include/exclude, review modes
|
|
137
141
|
- **Prompts** — inline/context/summary prompt templates
|
|
138
142
|
|
|
@@ -170,7 +174,7 @@ jobs:
|
|
|
170
174
|
runs-on: ubuntu-latest
|
|
171
175
|
steps:
|
|
172
176
|
- uses: actions/checkout@v4
|
|
173
|
-
- uses: Nikita-Filonov/ai-review@v0.
|
|
177
|
+
- uses: Nikita-Filonov/ai-review@v0.19.0
|
|
174
178
|
with:
|
|
175
179
|
review-command: ${{ inputs.review-command }}
|
|
176
180
|
env:
|
|
@@ -11,21 +11,31 @@ from ai_review.clients.github.pr.schema.files import GitHubGetPRFilesResponseSch
|
|
|
11
11
|
from ai_review.clients.github.pr.schema.pull_request import GitHubGetPRResponseSchema
|
|
12
12
|
from ai_review.clients.github.pr.schema.reviews import GitHubGetPRReviewsResponseSchema
|
|
13
13
|
from ai_review.libs.http.client import HTTPClient
|
|
14
|
+
from ai_review.libs.http.handlers import HTTPClientError, handle_http_error
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class GitHubPullRequestsHTTPClientError(HTTPClientError):
|
|
18
|
+
pass
|
|
14
19
|
|
|
15
20
|
|
|
16
21
|
class GitHubPullRequestsHTTPClient(HTTPClient):
|
|
22
|
+
@handle_http_error(client="GitHubPullRequestsHTTPClient", exception=GitHubPullRequestsHTTPClientError)
|
|
17
23
|
async def get_pull_request_api(self, owner: str, repo: str, pull_number: str) -> Response:
|
|
18
24
|
return await self.get(f"/repos/{owner}/{repo}/pulls/{pull_number}")
|
|
19
25
|
|
|
26
|
+
@handle_http_error(client="GitHubPullRequestsHTTPClient", exception=GitHubPullRequestsHTTPClientError)
|
|
20
27
|
async def get_files_api(self, owner: str, repo: str, pull_number: str) -> Response:
|
|
21
28
|
return await self.get(f"/repos/{owner}/{repo}/pulls/{pull_number}/files")
|
|
22
29
|
|
|
30
|
+
@handle_http_error(client="GitHubPullRequestsHTTPClient", exception=GitHubPullRequestsHTTPClientError)
|
|
23
31
|
async def get_issue_comments_api(self, owner: str, repo: str, issue_number: str) -> Response:
|
|
24
32
|
return await self.get(f"/repos/{owner}/{repo}/issues/{issue_number}/comments")
|
|
25
33
|
|
|
34
|
+
@handle_http_error(client="GitHubPullRequestsHTTPClient", exception=GitHubPullRequestsHTTPClientError)
|
|
26
35
|
async def get_review_comments_api(self, owner: str, repo: str, pull_number: str) -> Response:
|
|
27
36
|
return await self.get(f"/repos/{owner}/{repo}/pulls/{pull_number}/comments")
|
|
28
37
|
|
|
38
|
+
@handle_http_error(client="GitHubPullRequestsHTTPClient", exception=GitHubPullRequestsHTTPClientError)
|
|
29
39
|
async def create_review_comment_api(
|
|
30
40
|
self,
|
|
31
41
|
owner: str,
|
|
@@ -38,6 +48,7 @@ class GitHubPullRequestsHTTPClient(HTTPClient):
|
|
|
38
48
|
json=request.model_dump(),
|
|
39
49
|
)
|
|
40
50
|
|
|
51
|
+
@handle_http_error(client="GitHubPullRequestsHTTPClient", exception=GitHubPullRequestsHTTPClientError)
|
|
41
52
|
async def create_issue_comment_api(
|
|
42
53
|
self,
|
|
43
54
|
owner: str,
|
|
@@ -50,6 +61,7 @@ class GitHubPullRequestsHTTPClient(HTTPClient):
|
|
|
50
61
|
json=request.model_dump(),
|
|
51
62
|
)
|
|
52
63
|
|
|
64
|
+
@handle_http_error(client="GitHubPullRequestsHTTPClient", exception=GitHubPullRequestsHTTPClientError)
|
|
53
65
|
async def get_reviews_api(self, owner: str, repo: str, pull_number: str) -> Response:
|
|
54
66
|
return await self.get(f"/repos/{owner}/{repo}/pulls/{pull_number}/reviews")
|
|
55
67
|
|
|
@@ -78,14 +90,8 @@ class GitHubPullRequestsHTTPClient(HTTPClient):
|
|
|
78
90
|
owner: str,
|
|
79
91
|
repo: str,
|
|
80
92
|
pull_number: str,
|
|
81
|
-
|
|
82
|
-
commit_id: str,
|
|
83
|
-
path: str,
|
|
84
|
-
line: int,
|
|
93
|
+
request: GitHubCreateReviewCommentRequestSchema
|
|
85
94
|
) -> GitHubCreateReviewCommentResponseSchema:
|
|
86
|
-
request = GitHubCreateReviewCommentRequestSchema(
|
|
87
|
-
body=body, commit_id=commit_id, path=path, line=line
|
|
88
|
-
)
|
|
89
95
|
response = await self.create_review_comment_api(owner, repo, pull_number, request)
|
|
90
96
|
return GitHubCreateReviewCommentResponseSchema.model_validate_json(response.text)
|
|
91
97
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from pydantic import BaseModel
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class GitHubUserSchema(BaseModel):
|
|
@@ -8,13 +8,13 @@ class GitHubUserSchema(BaseModel):
|
|
|
8
8
|
|
|
9
9
|
class GitHubLabelSchema(BaseModel):
|
|
10
10
|
id: int
|
|
11
|
-
name: str
|
|
11
|
+
name: str | None = None
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class GitHubBranchSchema(BaseModel):
|
|
15
15
|
ref: str
|
|
16
16
|
sha: str
|
|
17
|
-
label: str
|
|
17
|
+
label: str | None = None
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class GitHubGetPRResponseSchema(BaseModel):
|
|
@@ -23,8 +23,8 @@ class GitHubGetPRResponseSchema(BaseModel):
|
|
|
23
23
|
title: str
|
|
24
24
|
body: str | None = None
|
|
25
25
|
user: GitHubUserSchema
|
|
26
|
-
labels: list[GitHubLabelSchema]
|
|
27
|
-
assignees: list[GitHubUserSchema] =
|
|
28
|
-
requested_reviewers: list[GitHubUserSchema] =
|
|
26
|
+
labels: list[GitHubLabelSchema] = Field(default_factory=list)
|
|
27
|
+
assignees: list[GitHubUserSchema] = Field(default_factory=list)
|
|
28
|
+
requested_reviewers: list[GitHubUserSchema] = Field(default_factory=list)
|
|
29
29
|
base: GitHubBranchSchema
|
|
30
30
|
head: GitHubBranchSchema
|
|
@@ -1,47 +1,56 @@
|
|
|
1
1
|
from httpx import Response
|
|
2
2
|
|
|
3
3
|
from ai_review.clients.gitlab.mr.schema.changes import GitLabGetMRChangesResponseSchema
|
|
4
|
-
from ai_review.clients.gitlab.mr.schema.comments import (
|
|
5
|
-
GitLabGetMRCommentsResponseSchema,
|
|
6
|
-
GitLabCreateMRCommentRequestSchema,
|
|
7
|
-
GitLabCreateMRCommentResponseSchema,
|
|
8
|
-
)
|
|
9
4
|
from ai_review.clients.gitlab.mr.schema.discussions import (
|
|
10
5
|
GitLabGetMRDiscussionsResponseSchema,
|
|
11
6
|
GitLabCreateMRDiscussionRequestSchema,
|
|
12
7
|
GitLabCreateMRDiscussionResponseSchema
|
|
13
8
|
)
|
|
9
|
+
from ai_review.clients.gitlab.mr.schema.notes import (
|
|
10
|
+
GitLabGetMRNotesResponseSchema,
|
|
11
|
+
GitLabCreateMRNoteRequestSchema,
|
|
12
|
+
GitLabCreateMRNoteResponseSchema,
|
|
13
|
+
)
|
|
14
14
|
from ai_review.libs.http.client import HTTPClient
|
|
15
|
+
from ai_review.libs.http.handlers import handle_http_error, HTTPClientError
|
|
15
16
|
|
|
16
17
|
|
|
17
|
-
class
|
|
18
|
+
class GitLabMergeRequestsHTTPClientError(HTTPClientError):
|
|
19
|
+
pass
|
|
18
20
|
|
|
21
|
+
|
|
22
|
+
class GitLabMergeRequestsHTTPClient(HTTPClient):
|
|
23
|
+
@handle_http_error(client="GitLabMergeRequestsHTTPClient", exception=GitLabMergeRequestsHTTPClientError)
|
|
19
24
|
async def get_changes_api(self, project_id: str, merge_request_id: str) -> Response:
|
|
20
25
|
return await self.get(
|
|
21
26
|
f"/api/v4/projects/{project_id}/merge_requests/{merge_request_id}/changes"
|
|
22
27
|
)
|
|
23
28
|
|
|
24
|
-
|
|
29
|
+
@handle_http_error(client="GitLabMergeRequestsHTTPClient", exception=GitLabMergeRequestsHTTPClientError)
|
|
30
|
+
async def get_notes_api(self, project_id: str, merge_request_id: str) -> Response:
|
|
25
31
|
return await self.get(
|
|
26
32
|
f"/api/v4/projects/{project_id}/merge_requests/{merge_request_id}/notes"
|
|
27
33
|
)
|
|
28
34
|
|
|
35
|
+
@handle_http_error(client="GitLabMergeRequestsHTTPClient", exception=GitLabMergeRequestsHTTPClientError)
|
|
29
36
|
async def get_discussions_api(self, project_id: str, merge_request_id: str) -> Response:
|
|
30
37
|
return await self.get(
|
|
31
38
|
f"/api/v4/projects/{project_id}/merge_requests/{merge_request_id}/discussions"
|
|
32
39
|
)
|
|
33
40
|
|
|
34
|
-
|
|
41
|
+
@handle_http_error(client="GitLabMergeRequestsHTTPClient", exception=GitLabMergeRequestsHTTPClientError)
|
|
42
|
+
async def create_note_api(
|
|
35
43
|
self,
|
|
36
44
|
project_id: str,
|
|
37
45
|
merge_request_id: str,
|
|
38
|
-
request:
|
|
46
|
+
request: GitLabCreateMRNoteRequestSchema,
|
|
39
47
|
) -> Response:
|
|
40
48
|
return await self.post(
|
|
41
49
|
f"/api/v4/projects/{project_id}/merge_requests/{merge_request_id}/notes",
|
|
42
50
|
json=request.model_dump(),
|
|
43
51
|
)
|
|
44
52
|
|
|
53
|
+
@handle_http_error(client="GitLabMergeRequestsHTTPClient", exception=GitLabMergeRequestsHTTPClientError)
|
|
45
54
|
async def create_discussion_api(
|
|
46
55
|
self,
|
|
47
56
|
project_id: str,
|
|
@@ -57,13 +66,13 @@ class GitLabMergeRequestsHTTPClient(HTTPClient):
|
|
|
57
66
|
response = await self.get_changes_api(project_id, merge_request_id)
|
|
58
67
|
return GitLabGetMRChangesResponseSchema.model_validate_json(response.text)
|
|
59
68
|
|
|
60
|
-
async def
|
|
69
|
+
async def get_notes(
|
|
61
70
|
self,
|
|
62
71
|
project_id: str,
|
|
63
72
|
merge_request_id: str
|
|
64
|
-
) ->
|
|
65
|
-
response = await self.
|
|
66
|
-
return
|
|
73
|
+
) -> GitLabGetMRNotesResponseSchema:
|
|
74
|
+
response = await self.get_notes_api(project_id, merge_request_id)
|
|
75
|
+
return GitLabGetMRNotesResponseSchema.model_validate_json(response.text)
|
|
67
76
|
|
|
68
77
|
async def get_discussions(
|
|
69
78
|
self,
|
|
@@ -73,26 +82,26 @@ class GitLabMergeRequestsHTTPClient(HTTPClient):
|
|
|
73
82
|
response = await self.get_discussions_api(project_id, merge_request_id)
|
|
74
83
|
return GitLabGetMRDiscussionsResponseSchema.model_validate_json(response.text)
|
|
75
84
|
|
|
76
|
-
async def
|
|
85
|
+
async def create_note(
|
|
77
86
|
self,
|
|
78
|
-
|
|
87
|
+
body: str,
|
|
79
88
|
project_id: str,
|
|
80
89
|
merge_request_id: str,
|
|
81
|
-
) ->
|
|
82
|
-
request =
|
|
83
|
-
response = await self.
|
|
90
|
+
) -> GitLabCreateMRNoteResponseSchema:
|
|
91
|
+
request = GitLabCreateMRNoteRequestSchema(body=body)
|
|
92
|
+
response = await self.create_note_api(
|
|
84
93
|
request=request,
|
|
85
94
|
project_id=project_id,
|
|
86
95
|
merge_request_id=merge_request_id
|
|
87
96
|
)
|
|
88
|
-
return
|
|
97
|
+
return GitLabCreateMRNoteResponseSchema.model_validate_json(response.text)
|
|
89
98
|
|
|
90
99
|
async def create_discussion(
|
|
91
100
|
self,
|
|
92
101
|
project_id: str,
|
|
93
102
|
merge_request_id: str,
|
|
94
103
|
request: GitLabCreateMRDiscussionRequestSchema
|
|
95
|
-
):
|
|
104
|
+
) -> GitLabCreateMRDiscussionResponseSchema:
|
|
96
105
|
response = await self.create_discussion_api(
|
|
97
106
|
request=request,
|
|
98
107
|
project_id=project_id,
|
|
@@ -14,9 +14,9 @@ class GitLabDiffRefsSchema(BaseModel):
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class GitLabMRChangeSchema(BaseModel):
|
|
17
|
-
diff: str
|
|
18
|
-
old_path: str
|
|
19
|
-
new_path: str
|
|
17
|
+
diff: str | None = None
|
|
18
|
+
old_path: str | None = None
|
|
19
|
+
new_path: str | None = None
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class GitLabGetMRChangesResponseSchema(BaseModel):
|
|
@@ -24,12 +24,12 @@ class GitLabGetMRChangesResponseSchema(BaseModel):
|
|
|
24
24
|
iid: int
|
|
25
25
|
title: str
|
|
26
26
|
author: GitLabUserSchema
|
|
27
|
-
labels: list[str] =
|
|
27
|
+
labels: list[str] = Field(default_factory=list)
|
|
28
28
|
changes: list[GitLabMRChangeSchema]
|
|
29
29
|
assignees: list[GitLabUserSchema] = Field(default_factory=list)
|
|
30
30
|
reviewers: list[GitLabUserSchema] = Field(default_factory=list)
|
|
31
31
|
diff_refs: GitLabDiffRefsSchema
|
|
32
32
|
project_id: int
|
|
33
|
-
description: str
|
|
33
|
+
description: str | None = None
|
|
34
34
|
source_branch: str
|
|
35
35
|
target_branch: str
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from pydantic import BaseModel, RootModel
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class GitLabNoteSchema(BaseModel):
|
|
5
|
+
id: int
|
|
6
|
+
body: str
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class GitLabGetMRNotesResponseSchema(RootModel[list[GitLabNoteSchema]]):
|
|
10
|
+
root: list[GitLabNoteSchema]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class GitLabCreateMRNoteRequestSchema(BaseModel):
|
|
14
|
+
body: str
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class GitLabCreateMRNoteResponseSchema(BaseModel):
|
|
18
|
+
id: int
|
|
19
|
+
body: str
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from ai_review.services.prompt.schema import PromptContextSchema
|
|
2
|
+
from ai_review.services.vcs.types import ReviewInfoSchema
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def build_prompt_context_from_mr_info(review: ReviewInfoSchema) -> PromptContextSchema:
|
|
6
|
+
return PromptContextSchema(
|
|
7
|
+
review_title=review.title,
|
|
8
|
+
review_description=review.description,
|
|
9
|
+
|
|
10
|
+
review_author_name=review.author.name,
|
|
11
|
+
review_author_username=review.author.username,
|
|
12
|
+
|
|
13
|
+
review_reviewers=[user.name for user in review.reviewers],
|
|
14
|
+
review_reviewers_usernames=[user.username for user in review.reviewers],
|
|
15
|
+
review_reviewer=review.reviewers[0].name if review.reviewers else "",
|
|
16
|
+
|
|
17
|
+
review_assignees=[user.name for user in review.assignees],
|
|
18
|
+
review_assignees_usernames=[user.username for user in review.assignees],
|
|
19
|
+
|
|
20
|
+
source_branch=review.source_branch.ref,
|
|
21
|
+
target_branch=review.target_branch.ref,
|
|
22
|
+
|
|
23
|
+
labels=review.labels,
|
|
24
|
+
changed_files=review.changed_files,
|
|
25
|
+
)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field
|
|
2
|
+
|
|
3
|
+
from ai_review.config import settings
|
|
4
|
+
from ai_review.libs.template.render import render_template
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class PromptContextSchema(BaseModel):
|
|
8
|
+
review_title: str = ""
|
|
9
|
+
review_description: str = ""
|
|
10
|
+
|
|
11
|
+
review_author_name: str = ""
|
|
12
|
+
review_author_username: str = ""
|
|
13
|
+
|
|
14
|
+
review_reviewer: str = ""
|
|
15
|
+
review_reviewers: list[str] = Field(default_factory=list)
|
|
16
|
+
review_reviewers_usernames: list[str] = Field(default_factory=list)
|
|
17
|
+
|
|
18
|
+
review_assignees: list[str] = Field(default_factory=list)
|
|
19
|
+
review_assignees_usernames: list[str] = Field(default_factory=list)
|
|
20
|
+
|
|
21
|
+
source_branch: str = ""
|
|
22
|
+
target_branch: str = ""
|
|
23
|
+
|
|
24
|
+
labels: list[str] = Field(default_factory=list)
|
|
25
|
+
changed_files: list[str] = Field(default_factory=list)
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def render_values(self) -> dict[str, str]:
|
|
29
|
+
return {
|
|
30
|
+
"review_title": self.review_title,
|
|
31
|
+
"review_description": self.review_description,
|
|
32
|
+
|
|
33
|
+
"review_author_name": self.review_author_name,
|
|
34
|
+
"review_author_username": self.review_author_username,
|
|
35
|
+
|
|
36
|
+
"review_reviewer": self.review_reviewer,
|
|
37
|
+
"review_reviewers": ", ".join(self.review_reviewers),
|
|
38
|
+
"review_reviewers_usernames": ", ".join(self.review_reviewers_usernames),
|
|
39
|
+
|
|
40
|
+
"review_assignees": ", ".join(self.review_assignees),
|
|
41
|
+
"review_assignees_usernames": ", ".join(self.review_assignees_usernames),
|
|
42
|
+
|
|
43
|
+
"source_branch": self.source_branch,
|
|
44
|
+
"target_branch": self.target_branch,
|
|
45
|
+
|
|
46
|
+
"labels": ", ".join(self.labels),
|
|
47
|
+
"changed_files": ", ".join(self.changed_files),
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
def apply_format(self, prompt: str) -> str:
|
|
51
|
+
values = {**self.render_values, **settings.prompt.context}
|
|
52
|
+
return render_template(prompt, values, settings.prompt.context_placeholder)
|