xai-review 0.21.0__py3-none-any.whl → 0.23.0__py3-none-any.whl

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 (63) hide show
  1. ai_review/clients/claude/client.py +1 -1
  2. ai_review/clients/gemini/client.py +1 -1
  3. ai_review/clients/github/client.py +1 -1
  4. ai_review/clients/github/pr/client.py +64 -16
  5. ai_review/clients/github/pr/schema/comments.py +4 -0
  6. ai_review/clients/github/pr/schema/files.py +4 -0
  7. ai_review/clients/github/pr/schema/reviews.py +4 -0
  8. ai_review/clients/github/pr/types.py +49 -0
  9. ai_review/clients/gitlab/client.py +1 -1
  10. ai_review/clients/gitlab/mr/client.py +25 -8
  11. ai_review/clients/gitlab/mr/schema/discussions.py +4 -0
  12. ai_review/clients/gitlab/mr/schema/notes.py +4 -0
  13. ai_review/clients/gitlab/mr/types.py +35 -0
  14. ai_review/clients/openai/client.py +1 -1
  15. ai_review/config.py +2 -0
  16. ai_review/libs/asynchronous/gather.py +6 -3
  17. ai_review/libs/config/core.py +5 -0
  18. ai_review/libs/http/event_hooks/logger.py +5 -2
  19. ai_review/libs/http/transports/retry.py +23 -6
  20. ai_review/services/diff/renderers.py +3 -3
  21. ai_review/services/prompt/schema.py +13 -24
  22. ai_review/tests/fixtures/clients/claude.py +22 -0
  23. ai_review/tests/fixtures/clients/gemini.py +21 -0
  24. ai_review/tests/fixtures/clients/github.py +181 -0
  25. ai_review/tests/fixtures/clients/gitlab.py +150 -0
  26. ai_review/tests/fixtures/clients/openai.py +21 -0
  27. ai_review/tests/fixtures/services/__init__.py +0 -0
  28. ai_review/tests/fixtures/services/review/__init__.py +0 -0
  29. ai_review/tests/suites/clients/claude/test_client.py +1 -20
  30. ai_review/tests/suites/clients/gemini/test_client.py +1 -19
  31. ai_review/tests/suites/clients/github/test_client.py +1 -23
  32. ai_review/tests/suites/clients/gitlab/test_client.py +1 -22
  33. ai_review/tests/suites/clients/openai/test_client.py +1 -19
  34. ai_review/tests/suites/libs/asynchronous/__init__.py +0 -0
  35. ai_review/tests/suites/libs/asynchronous/test_gather.py +46 -0
  36. ai_review/tests/suites/services/diff/test_service.py +1 -1
  37. ai_review/tests/suites/services/diff/test_tools.py +1 -1
  38. ai_review/tests/suites/services/llm/__init__.py +0 -0
  39. ai_review/tests/suites/services/llm/test_factory.py +30 -0
  40. ai_review/tests/suites/services/prompt/test_schema.py +65 -0
  41. ai_review/tests/suites/services/review/test_service.py +9 -9
  42. ai_review/tests/suites/services/vcs/__init__.py +0 -0
  43. ai_review/tests/suites/services/vcs/github/__init__.py +0 -0
  44. ai_review/tests/suites/services/vcs/github/test_service.py +114 -0
  45. ai_review/tests/suites/services/vcs/gitlab/__init__.py +0 -0
  46. ai_review/tests/suites/services/vcs/gitlab/test_service.py +123 -0
  47. ai_review/tests/suites/services/vcs/test_factory.py +23 -0
  48. {xai_review-0.21.0.dist-info → xai_review-0.23.0.dist-info}/METADATA +2 -2
  49. {xai_review-0.21.0.dist-info → xai_review-0.23.0.dist-info}/RECORD +63 -43
  50. /ai_review/tests/fixtures/{review → clients}/__init__.py +0 -0
  51. /ai_review/tests/fixtures/{artifacts.py → services/artifacts.py} +0 -0
  52. /ai_review/tests/fixtures/{cost.py → services/cost.py} +0 -0
  53. /ai_review/tests/fixtures/{diff.py → services/diff.py} +0 -0
  54. /ai_review/tests/fixtures/{git.py → services/git.py} +0 -0
  55. /ai_review/tests/fixtures/{llm.py → services/llm.py} +0 -0
  56. /ai_review/tests/fixtures/{prompt.py → services/prompt.py} +0 -0
  57. /ai_review/tests/fixtures/{review → services/review}/inline.py +0 -0
  58. /ai_review/tests/fixtures/{review → services/review}/summary.py +0 -0
  59. /ai_review/tests/fixtures/{vcs.py → services/vcs.py} +0 -0
  60. {xai_review-0.21.0.dist-info → xai_review-0.23.0.dist-info}/WHEEL +0 -0
  61. {xai_review-0.21.0.dist-info → xai_review-0.23.0.dist-info}/entry_points.txt +0 -0
  62. {xai_review-0.21.0.dist-info → xai_review-0.23.0.dist-info}/licenses/LICENSE +0 -0
  63. {xai_review-0.21.0.dist-info → xai_review-0.23.0.dist-info}/top_level.txt +0 -0
@@ -5,6 +5,7 @@ from ai_review.services.prompt.schema import PromptContextSchema
5
5
 
6
6
 
7
7
  def test_apply_format_inserts_variables() -> None:
8
+ """Ensures simple string fields are correctly substituted into the template."""
8
9
  context = PromptContextSchema(
9
10
  review_title="My Review",
10
11
  review_author_username="nikita"
@@ -15,6 +16,7 @@ def test_apply_format_inserts_variables() -> None:
15
16
 
16
17
 
17
18
  def test_apply_format_with_lists() -> None:
19
+ """Ensures list fields are serialized as CSV strings and substituted into the template."""
18
20
  context = PromptContextSchema(
19
21
  review_reviewers=["Alice", "Bob"],
20
22
  review_reviewers_usernames=["alice", "bob"],
@@ -35,6 +37,7 @@ def test_apply_format_with_lists() -> None:
35
37
 
36
38
 
37
39
  def test_apply_format_handles_missing_fields() -> None:
40
+ """Ensures missing fields are replaced with empty strings."""
38
41
  context = PromptContextSchema()
39
42
  template = "Title: <<review_title>>, Reviewer: <<review_reviewer>>"
40
43
  result = context.apply_format(template)
@@ -42,6 +45,7 @@ def test_apply_format_handles_missing_fields() -> None:
42
45
 
43
46
 
44
47
  def test_apply_format_unknown_placeholder_kept() -> None:
48
+ """Ensures unknown placeholders remain unchanged in the template."""
45
49
  context = PromptContextSchema()
46
50
  template = "Unknown: <<does_not_exist>>"
47
51
  result = context.apply_format(template)
@@ -49,6 +53,7 @@ def test_apply_format_unknown_placeholder_kept() -> None:
49
53
 
50
54
 
51
55
  def test_apply_format_multiple_occurrences() -> None:
56
+ """Ensures multiple occurrences of the same placeholder are all replaced."""
52
57
  context = PromptContextSchema(review_title="My Review")
53
58
  template = "<<review_title>> again <<review_title>>"
54
59
  result = context.apply_format(template)
@@ -56,6 +61,7 @@ def test_apply_format_multiple_occurrences() -> None:
56
61
 
57
62
 
58
63
  def test_apply_format_override_from_settings(monkeypatch: pytest.MonkeyPatch) -> None:
64
+ """Ensures values from settings.prompt.context override local model values."""
59
65
  monkeypatch.setitem(settings.prompt.context, "review_title", "Overridden")
60
66
  context = PromptContextSchema(review_title="Local Value")
61
67
  template = "Title: <<review_title>>"
@@ -64,8 +70,67 @@ def test_apply_format_override_from_settings(monkeypatch: pytest.MonkeyPatch) ->
64
70
 
65
71
 
66
72
  def test_apply_format_prefers_override_even_if_empty(monkeypatch: pytest.MonkeyPatch) -> None:
73
+ """Ensures overrides take precedence even if the override value is empty."""
67
74
  monkeypatch.setitem(settings.prompt.context, "review_title", "")
68
75
  context = PromptContextSchema(review_title="Local Value")
69
76
  template = "Title: <<review_title>>"
70
77
  result = context.apply_format(template)
71
78
  assert result == "Title: "
79
+
80
+
81
+ def test_apply_format_empty_list_serializes_to_empty_string() -> None:
82
+ """Ensures empty lists are serialized to empty strings."""
83
+ context = PromptContextSchema(labels=[])
84
+ template = "Labels: <<labels>>"
85
+ result = context.apply_format(template)
86
+ assert result == "Labels: "
87
+
88
+
89
+ def test_apply_format_single_element_list() -> None:
90
+ """Ensures lists with a single element are serialized without extra separators."""
91
+ context = PromptContextSchema(labels=["bug"])
92
+ template = "Labels: <<labels>>"
93
+ result = context.apply_format(template)
94
+ assert result == "Labels: bug"
95
+
96
+
97
+ def test_apply_format_list_with_spaces() -> None:
98
+ """Ensures list items containing spaces are preserved in serialization."""
99
+ context = PromptContextSchema(labels=[" bug ", " feature "])
100
+ template = "Labels: <<labels>>"
101
+ result = context.apply_format(template)
102
+ assert result == "Labels: bug , feature "
103
+
104
+
105
+ def test_apply_format_placeholder_case_sensitive() -> None:
106
+ """Ensures placeholder matching is case-sensitive."""
107
+ context = PromptContextSchema(review_title="My Review")
108
+ template = "Title: <<Review_Title>>"
109
+ result = context.apply_format(template)
110
+ assert result == "Title: <<Review_Title>>"
111
+
112
+
113
+ def test_apply_format_override_with_none(monkeypatch: pytest.MonkeyPatch) -> None:
114
+ """Ensures None in overrides is treated as an empty string."""
115
+ monkeypatch.setitem(settings.prompt.context, "review_title", None)
116
+ context = PromptContextSchema(review_title="Local Value")
117
+ template = "Title: <<review_title>>"
118
+ result = context.apply_format(template)
119
+ assert result == "Title: "
120
+
121
+
122
+ def test_apply_format_placeholder_inside_word() -> None:
123
+ """Ensures placeholders inside words are still replaced correctly."""
124
+ context = PromptContextSchema(review_title="REV")
125
+ template = "prefix-<<review_title>>-suffix"
126
+ result = context.apply_format(template)
127
+ assert result == "prefix-REV-suffix"
128
+
129
+
130
+ def test_apply_format_large_list() -> None:
131
+ """Ensures large lists are serialized correctly without truncation."""
132
+ context = PromptContextSchema(labels=[str(index) for index in range(100)])
133
+ template = "Labels: <<labels>>"
134
+ result = context.apply_format(template)
135
+ assert result.startswith("Labels: 0, 1, 2")
136
+ assert "99" in result
@@ -1,15 +1,15 @@
1
1
  import pytest
2
2
 
3
3
  from ai_review.services.review.service import ReviewService
4
- from ai_review.tests.fixtures.artifacts import FakeArtifactsService
5
- from ai_review.tests.fixtures.cost import FakeCostService
6
- from ai_review.tests.fixtures.diff import FakeDiffService
7
- from ai_review.tests.fixtures.git import FakeGitService
8
- from ai_review.tests.fixtures.llm import FakeLLMClient
9
- from ai_review.tests.fixtures.prompt import FakePromptService
10
- from ai_review.tests.fixtures.review.inline import FakeInlineCommentService
11
- from ai_review.tests.fixtures.review.summary import FakeSummaryCommentService
12
- from ai_review.tests.fixtures.vcs import FakeVCSClient
4
+ from ai_review.tests.fixtures.services.artifacts import FakeArtifactsService
5
+ from ai_review.tests.fixtures.services.cost import FakeCostService
6
+ from ai_review.tests.fixtures.services.diff import FakeDiffService
7
+ from ai_review.tests.fixtures.services.git import FakeGitService
8
+ from ai_review.tests.fixtures.services.llm import FakeLLMClient
9
+ from ai_review.tests.fixtures.services.prompt import FakePromptService
10
+ from ai_review.tests.fixtures.services.review.inline import FakeInlineCommentService
11
+ from ai_review.tests.fixtures.services.review.summary import FakeSummaryCommentService
12
+ from ai_review.tests.fixtures.services.vcs import FakeVCSClient
13
13
 
14
14
 
15
15
  @pytest.fixture
File without changes
File without changes
@@ -0,0 +1,114 @@
1
+ import pytest
2
+
3
+ from ai_review.services.vcs.github.client import GitHubVCSClient
4
+ from ai_review.services.vcs.types import ReviewInfoSchema, ReviewCommentSchema
5
+ from ai_review.tests.fixtures.clients.github import FakeGitHubPullRequestsHTTPClient
6
+
7
+
8
+ @pytest.mark.asyncio
9
+ @pytest.mark.usefixtures("github_http_client_config")
10
+ async def test_get_review_info_returns_valid_schema(
11
+ github_vcs_client: GitHubVCSClient,
12
+ fake_github_pull_requests_http_client: FakeGitHubPullRequestsHTTPClient,
13
+ ):
14
+ """Should return detailed PR info with branches, author, and files."""
15
+ info = await github_vcs_client.get_review_info()
16
+
17
+ assert isinstance(info, ReviewInfoSchema)
18
+ assert info.id == 1
19
+ assert info.title == "Fake Pull Request"
20
+ assert info.description == "This is a fake PR for testing"
21
+
22
+ assert info.author.username == "tester"
23
+ assert {a.username for a in info.assignees} == {"dev1", "dev2"}
24
+ assert {r.username for r in info.reviewers} == {"reviewer"}
25
+
26
+ assert info.source_branch.ref == "feature/test"
27
+ assert info.target_branch.ref == "main"
28
+ assert info.base_sha == "abc123"
29
+ assert info.head_sha == "def456"
30
+
31
+ assert "app/main.py" in info.changed_files
32
+ assert len(info.changed_files) == 2
33
+
34
+ called_methods = [name for name, _ in fake_github_pull_requests_http_client.calls]
35
+ assert called_methods == ["get_pull_request", "get_files"]
36
+
37
+
38
+ @pytest.mark.asyncio
39
+ @pytest.mark.usefixtures("github_http_client_config")
40
+ async def test_get_general_comments_returns_expected_list(
41
+ github_vcs_client: GitHubVCSClient,
42
+ fake_github_pull_requests_http_client: FakeGitHubPullRequestsHTTPClient,
43
+ ):
44
+ """Should return general (issue-level) comments."""
45
+ comments = await github_vcs_client.get_general_comments()
46
+
47
+ assert all(isinstance(c, ReviewCommentSchema) for c in comments)
48
+ assert len(comments) == 2
49
+
50
+ bodies = [c.body for c in comments]
51
+ assert "General comment" in bodies
52
+ assert "Another general comment" in bodies
53
+
54
+ called_methods = [name for name, _ in fake_github_pull_requests_http_client.calls]
55
+ assert called_methods == ["get_issue_comments"]
56
+
57
+
58
+ @pytest.mark.asyncio
59
+ @pytest.mark.usefixtures("github_http_client_config")
60
+ async def test_get_inline_comments_returns_expected_list(
61
+ github_vcs_client: GitHubVCSClient,
62
+ fake_github_pull_requests_http_client: FakeGitHubPullRequestsHTTPClient,
63
+ ):
64
+ """Should return inline comments with file and line references."""
65
+ comments = await github_vcs_client.get_inline_comments()
66
+
67
+ assert all(isinstance(c, ReviewCommentSchema) for c in comments)
68
+ assert len(comments) == 2
69
+
70
+ first = comments[0]
71
+ assert first.body == "Inline comment"
72
+ assert first.file == "file.py"
73
+ assert first.line == 5
74
+
75
+ called_methods = [name for name, _ in fake_github_pull_requests_http_client.calls]
76
+ assert called_methods == ["get_review_comments"]
77
+
78
+
79
+ @pytest.mark.asyncio
80
+ @pytest.mark.usefixtures("github_http_client_config")
81
+ async def test_create_general_comment_posts_comment(
82
+ github_vcs_client: GitHubVCSClient,
83
+ fake_github_pull_requests_http_client: FakeGitHubPullRequestsHTTPClient,
84
+ ):
85
+ """Should post a general (non-inline) comment."""
86
+ message = "Hello from test!"
87
+
88
+ await github_vcs_client.create_general_comment(message)
89
+
90
+ calls = [args for name, args in fake_github_pull_requests_http_client.calls if name == "create_issue_comment"]
91
+ assert len(calls) == 1
92
+ call_args = calls[0]
93
+ assert call_args["body"] == message
94
+ assert call_args["repo"] == "repo"
95
+ assert call_args["owner"] == "owner"
96
+
97
+
98
+ @pytest.mark.asyncio
99
+ @pytest.mark.usefixtures("github_http_client_config")
100
+ async def test_create_inline_comment_posts_comment(
101
+ github_vcs_client: GitHubVCSClient,
102
+ fake_github_pull_requests_http_client: FakeGitHubPullRequestsHTTPClient,
103
+ ):
104
+ """Should post an inline comment with correct path, line and commit_id."""
105
+ await github_vcs_client.create_inline_comment("file.py", 10, "Looks good")
106
+
107
+ calls = [args for name, args in fake_github_pull_requests_http_client.calls if name == "create_review_comment"]
108
+ assert len(calls) == 1
109
+
110
+ call_args = calls[0]
111
+ assert call_args["path"] == "file.py"
112
+ assert call_args["line"] == 10
113
+ assert call_args["body"] == "Looks good"
114
+ assert call_args["commit_id"] == "def456" # from fake PR head
File without changes
@@ -0,0 +1,123 @@
1
+ import pytest
2
+
3
+ from ai_review.services.vcs.gitlab.client import GitLabVCSClient
4
+ from ai_review.services.vcs.types import ReviewInfoSchema, ReviewCommentSchema
5
+ from ai_review.tests.fixtures.clients.gitlab import FakeGitLabMergeRequestsHTTPClient
6
+
7
+
8
+ @pytest.mark.asyncio
9
+ @pytest.mark.usefixtures("gitlab_http_client_config")
10
+ async def test_get_review_info_returns_valid_schema(
11
+ gitlab_vcs_client: GitLabVCSClient,
12
+ fake_gitlab_merge_requests_http_client: FakeGitLabMergeRequestsHTTPClient,
13
+ ):
14
+ """Should return valid MR info with author, branches and changed files."""
15
+ info = await gitlab_vcs_client.get_review_info()
16
+
17
+ assert isinstance(info, ReviewInfoSchema)
18
+ assert info.id == 1
19
+ assert info.title == "Fake Merge Request"
20
+ assert info.description == "This is a fake MR for testing"
21
+
22
+ assert info.author.username == "tester"
23
+ assert info.author.name == "Tester"
24
+ assert info.author.id == 42
25
+
26
+ assert info.source_branch.ref == "feature/test"
27
+ assert info.target_branch.ref == "main"
28
+ assert info.base_sha == "abc123"
29
+ assert info.head_sha == "def456"
30
+ assert info.start_sha == "ghi789"
31
+
32
+ assert len(info.changed_files) == 1
33
+ assert info.changed_files[0] == "main.py"
34
+
35
+ called_methods = [name for name, _ in fake_gitlab_merge_requests_http_client.calls]
36
+ assert called_methods == ["get_changes"]
37
+
38
+
39
+ @pytest.mark.asyncio
40
+ @pytest.mark.usefixtures("gitlab_http_client_config")
41
+ async def test_get_general_comments_returns_expected_list(
42
+ gitlab_vcs_client: GitLabVCSClient,
43
+ fake_gitlab_merge_requests_http_client: FakeGitLabMergeRequestsHTTPClient,
44
+ ):
45
+ """Should return general MR-level notes."""
46
+ comments = await gitlab_vcs_client.get_general_comments()
47
+
48
+ assert all(isinstance(c, ReviewCommentSchema) for c in comments)
49
+ assert len(comments) == 2
50
+
51
+ bodies = [c.body for c in comments]
52
+ assert "General comment" in bodies
53
+ assert "Another note" in bodies
54
+
55
+ called_methods = [name for name, _ in fake_gitlab_merge_requests_http_client.calls]
56
+ assert called_methods == ["get_notes"]
57
+
58
+
59
+ @pytest.mark.asyncio
60
+ @pytest.mark.usefixtures("gitlab_http_client_config")
61
+ async def test_get_inline_comments_returns_expected_list(
62
+ gitlab_vcs_client: GitLabVCSClient,
63
+ fake_gitlab_merge_requests_http_client: FakeGitLabMergeRequestsHTTPClient,
64
+ ):
65
+ """Should return inline comments from MR discussions."""
66
+ comments = await gitlab_vcs_client.get_inline_comments()
67
+
68
+ assert all(isinstance(c, ReviewCommentSchema) for c in comments)
69
+ assert len(comments) == 2
70
+
71
+ first = comments[0]
72
+ assert first.body == "Inline comment A"
73
+
74
+ called_methods = [name for name, _ in fake_gitlab_merge_requests_http_client.calls]
75
+ assert called_methods == ["get_discussions"]
76
+
77
+
78
+ @pytest.mark.asyncio
79
+ @pytest.mark.usefixtures("gitlab_http_client_config")
80
+ async def test_create_general_comment_posts_comment(
81
+ gitlab_vcs_client: GitLabVCSClient,
82
+ fake_gitlab_merge_requests_http_client: FakeGitLabMergeRequestsHTTPClient,
83
+ ):
84
+ """Should post a general note to MR."""
85
+ message = "Hello, GitLab!"
86
+
87
+ await gitlab_vcs_client.create_general_comment(message)
88
+
89
+ calls = [
90
+ args for name, args in fake_gitlab_merge_requests_http_client.calls
91
+ if name == "create_note"
92
+ ]
93
+ assert len(calls) == 1
94
+ call_args = calls[0]
95
+
96
+ assert call_args["body"] == message
97
+ assert call_args["project_id"] == "project-id"
98
+ assert call_args["merge_request_id"] == "merge-request-id"
99
+
100
+
101
+ @pytest.mark.asyncio
102
+ @pytest.mark.usefixtures("gitlab_http_client_config")
103
+ async def test_create_inline_comment_posts_comment(
104
+ gitlab_vcs_client: GitLabVCSClient,
105
+ fake_gitlab_merge_requests_http_client: FakeGitLabMergeRequestsHTTPClient,
106
+ ):
107
+ """Should create an inline discussion at specific file and line."""
108
+ await gitlab_vcs_client.create_inline_comment("main.py", 5, "Looks good!")
109
+
110
+ called_names = [name for name, _ in fake_gitlab_merge_requests_http_client.calls]
111
+ assert "get_changes" in called_names
112
+ assert "create_discussion" in called_names
113
+
114
+ calls = [
115
+ args for name, args in fake_gitlab_merge_requests_http_client.calls
116
+ if name == "create_discussion"
117
+ ]
118
+ assert len(calls) == 1
119
+
120
+ call_args = calls[0]
121
+ assert call_args["body"] == "Looks good!"
122
+ assert call_args["project_id"] == "project-id"
123
+ assert call_args["merge_request_id"] == "merge-request-id"
@@ -0,0 +1,23 @@
1
+ import pytest
2
+
3
+ from ai_review.services.vcs.factory import get_vcs_client
4
+ from ai_review.services.vcs.github.client import GitHubVCSClient
5
+ from ai_review.services.vcs.gitlab.client import GitLabVCSClient
6
+
7
+
8
+ @pytest.mark.usefixtures("github_http_client_config")
9
+ def test_get_vcs_client_returns_github(monkeypatch: pytest.MonkeyPatch):
10
+ client = get_vcs_client()
11
+ assert isinstance(client, GitHubVCSClient)
12
+
13
+
14
+ @pytest.mark.usefixtures("gitlab_http_client_config")
15
+ def test_get_vcs_client_returns_gitlab(monkeypatch: pytest.MonkeyPatch):
16
+ client = get_vcs_client()
17
+ assert isinstance(client, GitLabVCSClient)
18
+
19
+
20
+ def test_get_vcs_client_unsupported_provider(monkeypatch: pytest.MonkeyPatch):
21
+ monkeypatch.setattr("ai_review.services.vcs.factory.settings.vcs.provider", "BITBUCKET")
22
+ with pytest.raises(ValueError):
23
+ get_vcs_client()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xai-review
3
- Version: 0.21.0
3
+ Version: 0.23.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>
@@ -209,7 +209,7 @@ jobs:
209
209
  runs-on: ubuntu-latest
210
210
  steps:
211
211
  - uses: actions/checkout@v4
212
- - uses: Nikita-Filonov/ai-review@v0.21.0
212
+ - uses: Nikita-Filonov/ai-review@v0.23.0
213
213
  with:
214
214
  review-command: ${{ inputs.review-command }}
215
215
  env:
@@ -1,5 +1,5 @@
1
1
  ai_review/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- ai_review/config.py,sha256=t3lhgbI58GjU5Wt7M-wVn0RyPcN51JPiMPOJQ39sT-M,1868
2
+ ai_review/config.py,sha256=tPda0l_EX6MWHtKXE6HLFIkzYqLxA2yogSQDMeE5MAM,1954
3
3
  ai_review/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  ai_review/cli/main.py,sha256=rZ0LYSAt3AFT-wOHdop8lq2GOVAK48kJYp7nf801Mjs,1854
5
5
  ai_review/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -9,41 +9,44 @@ ai_review/cli/commands/run_review.py,sha256=i39IYNDE_lAiQQnKLmxG71Ao8WAIOSn82L9E
9
9
  ai_review/cli/commands/run_summary_review.py,sha256=NqjepGH5cbqczPzcuMEAxO4dI58FEUZl0b6uRVQ9SiA,224
10
10
  ai_review/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  ai_review/clients/claude/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- ai_review/clients/claude/client.py,sha256=RRr9CW1F2pPYTPq2ySkc1t5vbuz4sDo8N7RETfjzZ4I,1781
12
+ ai_review/clients/claude/client.py,sha256=MKN7W5RRvV_zRWZLCLx75ATj-gtkef-YE7-Yd7C3ke8,1796
13
13
  ai_review/clients/claude/schema.py,sha256=LE6KCjJKDXqBGU2Cno5XL5R8vUfScgskE9MqvE0Pt2A,887
14
14
  ai_review/clients/gemini/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- ai_review/clients/gemini/client.py,sha256=7ZPgqx77ER7gonxX0VoN4YrMpex3iBEQtd9Hi-bnDms,1780
15
+ ai_review/clients/gemini/client.py,sha256=a-QY_4lDgZgUcEZpaeNjrqthWhXQ7iqdE_8pQROxqR0,1795
16
16
  ai_review/clients/gemini/schema.py,sha256=5oVvbI-h_sw8bFreS4JUmMj-aXa_frvxK3H8sg4iJIA,2264
17
17
  ai_review/clients/github/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- ai_review/clients/github/client.py,sha256=4uZsnMY-OZ9BNzMLqEHG80jgpyQdd61ePNdVuwGMcrI,1134
18
+ ai_review/clients/github/client.py,sha256=pprQcCYdrhRYtuqRsTFiCbj54Qb1Ll6_jmlm7AJg8pk,1149
19
19
  ai_review/clients/github/pr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- ai_review/clients/github/pr/client.py,sha256=sANW1K2MomgHzH4beqkkfHaEY2sRxiAVCDXjspOmcHA,5402
20
+ ai_review/clients/github/pr/client.py,sha256=YvGc4ClK615PgWslD8bL54pk1YakXHivabjnPZ8p6iI,6642
21
+ ai_review/clients/github/pr/types.py,sha256=mI5Vtlxc25iymOTPkNl55IQygXd4ti3B1Ydpx3q1fps,1726
21
22
  ai_review/clients/github/pr/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- ai_review/clients/github/pr/schema/comments.py,sha256=K9KQ9TmWv9Hjw8uTrCPkzyAVbFohjCCf_rww6Ucj3wM,650
23
- ai_review/clients/github/pr/schema/files.py,sha256=mLHg1CfXUKCdQf5YUtuJ8n6xOROKoAjiJY5PL70kP-w,269
23
+ ai_review/clients/github/pr/schema/comments.py,sha256=IjBtpcJABlql97_N7_CMAKuAozbVnSkaD16l3KueGqk,719
24
+ ai_review/clients/github/pr/schema/files.py,sha256=mXfmjaJuVbbo2PPTppCyYlc4LSd04fb-_x_9aJkNW04,335
24
25
  ai_review/clients/github/pr/schema/pull_request.py,sha256=EwOworYQY4kCmL6QFKEXK7r2fpINK8o-4-FEy9-nTpg,688
25
- ai_review/clients/github/pr/schema/reviews.py,sha256=v99DLYT5LOAcc18PATIse1mld8J0wKEAaTzUKI70s0c,288
26
+ ai_review/clients/github/pr/schema/reviews.py,sha256=tRHqGPzZ-LTbAZhtoVeBdl-LH34tgI0zPCtJTfFe2Mc,356
26
27
  ai_review/clients/gitlab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
- ai_review/clients/gitlab/client.py,sha256=acMflkHGp8mv0TVLdZ1gmdXkWQPcq609QjmkYWjEmys,1136
28
+ ai_review/clients/gitlab/client.py,sha256=MIZed-V4JUzntkU9vJq7Fkp5VAjnzjvep_5QM5ni_Co,1151
28
29
  ai_review/clients/gitlab/mr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- ai_review/clients/gitlab/mr/client.py,sha256=IeLq4-aL6k9-4W_-bhCwsujKSUvT68oBB6YlgSsS_VQ,4522
30
+ ai_review/clients/gitlab/mr/client.py,sha256=WdaJCJdSHeZZUQ9Hz8172RCgACwm-_NmcC91LHT7YwU,5158
31
+ ai_review/clients/gitlab/mr/types.py,sha256=tZ3rDDkzJM8v4zPt4gTyKCL30htiPQE9F_kVR6K5JHA,1280
30
32
  ai_review/clients/gitlab/mr/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
33
  ai_review/clients/gitlab/mr/schema/changes.py,sha256=ZqSPb8zO0z_V8cEjxoTqnwbjRLxo6OTV4LeQEAg91cU,835
32
- ai_review/clients/gitlab/mr/schema/discussions.py,sha256=DZqZTpLErmwSEsYSp6-XeBUo1kmFj3q6Zn_f3b6N9kk,718
33
- ai_review/clients/gitlab/mr/schema/notes.py,sha256=Vm-OZ9z34h57FtzazSQSZ5ZFnq6Sw568zG3R99TQTzI,358
34
+ ai_review/clients/gitlab/mr/schema/discussions.py,sha256=JgvxKfHoYxmp86aP4MpIczK-arU0hc-BZLASWDWBIRs,790
35
+ ai_review/clients/gitlab/mr/schema/notes.py,sha256=yfnnRt69fALKfapzZpVtvCvNwPkq5jBFI7fbPMq1w1c,424
34
36
  ai_review/clients/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- ai_review/clients/openai/client.py,sha256=N07ZRnbptOtab8imMUZbGL-kRoOwIZmNYbHySumD3IU,1707
37
+ ai_review/clients/openai/client.py,sha256=IWIl5um4chLiz45Hw1hd_KAz7jkXpJp0l2qf0ztMUV0,1722
36
38
  ai_review/clients/openai/schema.py,sha256=glxwMtBrDA6W0BQgH-ruKe0bKH3Ps1P-Y1-2jGdqaUM,764
37
39
  ai_review/libs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
40
  ai_review/libs/json.py,sha256=g-P5_pNUomQ-bGHCXASvPKj9Og0s9MaLFVEAkzqGp1A,350
39
41
  ai_review/libs/logger.py,sha256=LbXR2Zk1btJ-83I-vHee7cUETgT1mHToSsqEI_8uM0U,370
40
42
  ai_review/libs/resources.py,sha256=s9taAbL1Shl_GiGkPpkkivUcM1Yh6d_IQAG97gffsJU,748
41
43
  ai_review/libs/asynchronous/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
- ai_review/libs/asynchronous/gather.py,sha256=7YnZH7Y0IZxOSyFmQOFL3vNxsSz1ErIeB3uXoOyqN_M,431
44
+ ai_review/libs/asynchronous/gather.py,sha256=wH65sqBfrnwA1A9Juc5MSyLCJrcxzRqk2m0tSZ1tX8A,490
43
45
  ai_review/libs/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
46
  ai_review/libs/config/artifacts.py,sha256=8BzbQu5GxwV6i6qzrUKM1De1Ogb00Ph5WTqwZ3fVpGg,483
45
47
  ai_review/libs/config/base.py,sha256=sPf3OKeF1ID0ouOwiVaUtvpWuZXJXQvIw5kbnPUyN9o,686
46
48
  ai_review/libs/config/claude.py,sha256=E9AJmszfY4TH8PkJjnDDDJYNAU9bLGsUThM3kriVA58,302
49
+ ai_review/libs/config/core.py,sha256=ZQ2QtYr7vAF0tXbVLvVwk9QFE5h6JjAKAUQWcb9gHws,87
47
50
  ai_review/libs/config/gemini.py,sha256=sXHud43LWb4xTvhdkGQeHSLC7qvWl5LfU41fgcIVE5E,274
48
51
  ai_review/libs/config/github.py,sha256=1yFfvkTOt5ernIrxjqmiUKDpbEEHpa6lTpDiFQ5gVn4,238
49
52
  ai_review/libs/config/gitlab.py,sha256=VFvoVtni86tWky6Y34XCYdNrBuAtbgFFYGK3idPSOS4,234
@@ -66,9 +69,9 @@ ai_review/libs/http/client.py,sha256=JONzbhJWJKFz8Jy6p9pzq2hAMKlyJ2_WkBksuAlqW7k
66
69
  ai_review/libs/http/handlers.py,sha256=k1VvCIFjLzfH3qQ--aj4CZVgbU0oj78sYStMBrxo_Ek,1040
67
70
  ai_review/libs/http/event_hooks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
68
71
  ai_review/libs/http/event_hooks/base.py,sha256=cnSOOButTJYKeyb_OnGms1vXRfwfExP81L3ZfYWLufk,279
69
- ai_review/libs/http/event_hooks/logger.py,sha256=CcGk4dmxrOTwsM-QgTHQiJdI8cgLAG-Ay56iygOUCKU,546
72
+ ai_review/libs/http/event_hooks/logger.py,sha256=8_omfl6q3JijaBBIgzvzb4SayjNEDW-oxyck_Ky8wnI,603
70
73
  ai_review/libs/http/transports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
- ai_review/libs/http/transports/retry.py,sha256=WfY36SEMokjP0-uGv_OKlsaAVpMgePc1aYw3Eq4evTE,1145
74
+ ai_review/libs/http/transports/retry.py,sha256=OIhTplK22RigjF5A8M9FdMm01BLyWpvQnuK2__NC678,1768
72
75
  ai_review/libs/template/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
76
  ai_review/libs/template/render.py,sha256=PwLG46fXg8P3gZvmJB93P51G2IBdsEK2I8oDlLGmA-4,414
74
77
  ai_review/prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -91,7 +94,7 @@ ai_review/services/cost/schema.py,sha256=K3uCIMMxGL8AaIPh4a-d0mT5uIJuk3f805DkP8o
91
94
  ai_review/services/cost/service.py,sha256=-qbGePoL0oYnEC60Q5gQtd1IH8ucsOiF4349ueZl7Ts,2186
92
95
  ai_review/services/cost/types.py,sha256=VyQiF5uH5T7wYlOqkvxlCOjHnjWRu4CMo8j26hQ2Alo,341
93
96
  ai_review/services/diff/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
94
- ai_review/services/diff/renderers.py,sha256=tEUml-uqsi5FNoU2NYjxehsZHU61dTPR2VnFi7QVzV4,5861
97
+ ai_review/services/diff/renderers.py,sha256=Z5_ViB9KJu0o3k8TBtymbUqLv9QATt1gbqT2hrysJMQ,5885
95
98
  ai_review/services/diff/schema.py,sha256=17GAQY1-ySwREJ1-NKNKgBcstMJ5Hb42FcFG2p7i6Rs,94
96
99
  ai_review/services/diff/service.py,sha256=yRb4e0fZcgFTGkAZKm5q8Gw4rWxc3nyFtpBw7ahlnw8,3581
97
100
  ai_review/services/diff/tools.py,sha256=YHmH6Ult_rucCd563UhG0geMzqrPhqKFZKyug79xNuA,1963
@@ -114,7 +117,7 @@ ai_review/services/llm/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
114
117
  ai_review/services/llm/openai/client.py,sha256=c3DWwLnwTheERdSGnMiQIbg5SaICouUAGClcQZSh1fE,1159
115
118
  ai_review/services/prompt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
116
119
  ai_review/services/prompt/adapter.py,sha256=YgD8Cf73pwPOnKxq9QSlbYr8wySfDxJE_3fIrRWfkUo,984
117
- ai_review/services/prompt/schema.py,sha256=x-1KRFOK3HdZozXJNPh-Bp_JrZ2AIdAPD44lhWG5g9k,1863
120
+ ai_review/services/prompt/schema.py,sha256=ttla_lkvBQ-jfaZXzWSAAUrJROYRsozHHd5IoZc59zA,1324
118
121
  ai_review/services/prompt/service.py,sha256=58OJ6nIPSgXQyAqUXkWAXYAbNz7vMRemtllvD7bvQv0,2218
119
122
  ai_review/services/prompt/tools.py,sha256=-gS74mVM3OZPKWQkY9_QfStkfxaUfssDbJ3Bdi4AQ74,636
120
123
  ai_review/services/prompt/types.py,sha256=uVcvW8ZuwmM02MjCmw6Rg-IW5pIT3MeEYl0Vl-jzV4M,913
@@ -142,33 +145,42 @@ ai_review/services/vcs/gitlab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
142
145
  ai_review/services/vcs/gitlab/client.py,sha256=LK95m-uFSxhDEVU-cBGct61NTKjul-ieLZPxfBLIPts,6730
143
146
  ai_review/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
144
147
  ai_review/tests/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
145
- ai_review/tests/fixtures/artifacts.py,sha256=V5FvUnC9OAo0n-paxxJP5OxAgLz1Zz3OZ8zZvqu_01w,1462
146
- ai_review/tests/fixtures/cost.py,sha256=A6Ja0CtQ-k6pR2-B5LRE8EzkqPL34xHGXYtaILjhYvw,1612
147
- ai_review/tests/fixtures/diff.py,sha256=rOLFR-giYJlE2qUYTOT9BxyJhQ-fbXDdYCw3zed4-9M,1471
148
- ai_review/tests/fixtures/git.py,sha256=zDNNLZDoVC7r4LuF1N1MUgzhcAl2nhDdFC9olpR_PjQ,1441
149
- ai_review/tests/fixtures/llm.py,sha256=Wztlk0C2va_2z378dPwKoaQKFHSh5k7HWJkn-LY-k-8,886
150
- ai_review/tests/fixtures/prompt.py,sha256=dk0zretwVGTc0Pzt73zKf8Q36Vo7F_3s4O5NfTjfVqE,1920
151
- ai_review/tests/fixtures/vcs.py,sha256=Nz76T82DT7V0nVBWrchTKKHAy27KJKQGToNHfpG_bTM,1751
152
- ai_review/tests/fixtures/review/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
153
- ai_review/tests/fixtures/review/inline.py,sha256=k4IW6oy5JHMo9Kv0H97DLlFyrGsEInaozObjLARzdPg,1041
154
- ai_review/tests/fixtures/review/summary.py,sha256=Hkt8mq1ZmqMH5_mELrS1x0wtCoNPbBjOEQ9yIsMbRts,691
148
+ ai_review/tests/fixtures/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
149
+ ai_review/tests/fixtures/clients/claude.py,sha256=CpB65Twi2Q4kIOclflnyT--wGNrLPCEEgt9P_qyhu10,759
150
+ ai_review/tests/fixtures/clients/gemini.py,sha256=UXlLEqyXlei3ojrVCYRX0ic3Lq7iBNrG6BFZ8Ec_K7c,737
151
+ ai_review/tests/fixtures/clients/github.py,sha256=vZu_Tf8RlvYKDyMUnlP9Uc8fL95HRs1VTv7zWxIH_eQ,6856
152
+ ai_review/tests/fixtures/clients/gitlab.py,sha256=qyzp6lYZ9EQz-ECujFa5WK_xSbE-hmy35cfnW11mS6g,5531
153
+ ai_review/tests/fixtures/clients/openai.py,sha256=O30n-tCfpeCxeUQgrQPK5ll__buhbeShobK7LASFMls,721
154
+ ai_review/tests/fixtures/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
155
+ ai_review/tests/fixtures/services/artifacts.py,sha256=V5FvUnC9OAo0n-paxxJP5OxAgLz1Zz3OZ8zZvqu_01w,1462
156
+ ai_review/tests/fixtures/services/cost.py,sha256=A6Ja0CtQ-k6pR2-B5LRE8EzkqPL34xHGXYtaILjhYvw,1612
157
+ ai_review/tests/fixtures/services/diff.py,sha256=rOLFR-giYJlE2qUYTOT9BxyJhQ-fbXDdYCw3zed4-9M,1471
158
+ ai_review/tests/fixtures/services/git.py,sha256=zDNNLZDoVC7r4LuF1N1MUgzhcAl2nhDdFC9olpR_PjQ,1441
159
+ ai_review/tests/fixtures/services/llm.py,sha256=Wztlk0C2va_2z378dPwKoaQKFHSh5k7HWJkn-LY-k-8,886
160
+ ai_review/tests/fixtures/services/prompt.py,sha256=dk0zretwVGTc0Pzt73zKf8Q36Vo7F_3s4O5NfTjfVqE,1920
161
+ ai_review/tests/fixtures/services/vcs.py,sha256=Nz76T82DT7V0nVBWrchTKKHAy27KJKQGToNHfpG_bTM,1751
162
+ ai_review/tests/fixtures/services/review/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
163
+ ai_review/tests/fixtures/services/review/inline.py,sha256=k4IW6oy5JHMo9Kv0H97DLlFyrGsEInaozObjLARzdPg,1041
164
+ ai_review/tests/fixtures/services/review/summary.py,sha256=Hkt8mq1ZmqMH5_mELrS1x0wtCoNPbBjOEQ9yIsMbRts,691
155
165
  ai_review/tests/suites/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
156
166
  ai_review/tests/suites/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
157
167
  ai_review/tests/suites/clients/claude/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
158
- ai_review/tests/suites/clients/claude/test_client.py,sha256=X5X04veyKCnS9z3t13tTmw_GfBIM7grpFHxS0vctODA,1088
168
+ ai_review/tests/suites/clients/claude/test_client.py,sha256=jLGqK7lzYc8LjJO-3HjBtLqCdg-ubw-xZ4EvFeFGRhY,404
159
169
  ai_review/tests/suites/clients/claude/test_schema.py,sha256=MUZXvEROgLNpUVHfCsH5D3ruJPQwTx0OgeT3_BRVjgI,1671
160
170
  ai_review/tests/suites/clients/gemini/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
161
- ai_review/tests/suites/clients/gemini/test_client.py,sha256=6hxpK7r7iZVbOzAffRNDJnA63-3Zxvqw5ynANPhBhBg,1066
171
+ ai_review/tests/suites/clients/gemini/test_client.py,sha256=f2R7KisiENrzf8gaK26NYQZpQ1dvGHykZZ-eN_xC1UQ,404
162
172
  ai_review/tests/suites/clients/gemini/test_schema.py,sha256=88dU28m7sEWvGx6tqYl7if7weWYuVc8erlkFkKKI3bk,3109
163
173
  ai_review/tests/suites/clients/github/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
164
- ai_review/tests/suites/clients/github/test_client.py,sha256=iCFQRaDPNota21No5SaCwMvWRW4VTJu_MgmeCC4Dk2o,1328
174
+ ai_review/tests/suites/clients/github/test_client.py,sha256=BiuLKCHIk83U1szYEZkB-n3vvyPgj6tAI5EqxKiT-CY,558
165
175
  ai_review/tests/suites/clients/gitlab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
166
- ai_review/tests/suites/clients/gitlab/test_client.py,sha256=vXN7UZLC2yc7P7GZftpVvvUDycqR231ZFnfHZk97VLY,1325
176
+ ai_review/tests/suites/clients/gitlab/test_client.py,sha256=5QOkNvgm0XRKHh79FNIY9CTonAqYPXqCCxcxeiAHYCA,560
167
177
  ai_review/tests/suites/clients/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
168
- ai_review/tests/suites/clients/openai/test_client.py,sha256=Ox5ifP1C_gSeDRacBa9DnXhe__Z8-WcbzR2JH_V3xKo,1050
178
+ ai_review/tests/suites/clients/openai/test_client.py,sha256=6Wsxw6-6Uk0uPYFkzpWSwsxfCYUZhT3UYznayo-xlPI,404
169
179
  ai_review/tests/suites/clients/openai/test_schema.py,sha256=x1tamS4GC9pOTpjieKDbK2D73CVV4BkATppytwMevLo,1599
170
180
  ai_review/tests/suites/libs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
171
181
  ai_review/tests/suites/libs/test_json.py,sha256=q_tvFcL9EaN5jr48Ed_mxMEmW6xXS0xlZGqSooPZBa4,713
182
+ ai_review/tests/suites/libs/asynchronous/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
183
+ ai_review/tests/suites/libs/asynchronous/test_gather.py,sha256=Uzo0ctGFlllJU6TqA6hVWu_mcycJBAX5am8_bDO2eXk,1282
172
184
  ai_review/tests/suites/libs/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
173
185
  ai_review/tests/suites/libs/config/test_prompt.py,sha256=kDMTnykC54tTPfE6cqYRBbV8d5jzAKucXdJfwtqUybM,2242
174
186
  ai_review/tests/suites/libs/diff/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -183,17 +195,19 @@ ai_review/tests/suites/services/cost/test_schema.py,sha256=AI3Wg1sR6nzLpkEqJGDu6
183
195
  ai_review/tests/suites/services/cost/test_service.py,sha256=fMW4Tg6BRMXKcqOO7MmSqJc1mpuguvFSl0GjS93m7u8,3253
184
196
  ai_review/tests/suites/services/diff/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
185
197
  ai_review/tests/suites/services/diff/test_renderers.py,sha256=IKOpsGedONNW8ZfYTAk0Vq0hfFi7L6TpWs8vVVQroj0,6273
186
- ai_review/tests/suites/services/diff/test_service.py,sha256=xQbgbVHO2cdhv738rvxuZb1knnbCmjuLAvaAeMXnFkA,3186
187
- ai_review/tests/suites/services/diff/test_tools.py,sha256=cn1c5swLx-0rUZUFPtazn8kbIdNg63IgnTKVjHtbMSM,3615
198
+ ai_review/tests/suites/services/diff/test_service.py,sha256=evFe1I-ulOYdkhQS9NC8Bol4jXuhEnb2iArTAzckWrA,3195
199
+ ai_review/tests/suites/services/diff/test_tools.py,sha256=vsOSSIDZKkuD8dMCoBBEBt7WcYTNgxxCR6YNv2HEqqk,3624
188
200
  ai_review/tests/suites/services/hook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
189
201
  ai_review/tests/suites/services/hook/test_service.py,sha256=GM_AiNVGP2Pgp-3BwGOAIfA8lLXl6ah28ey77KZz_C4,2750
202
+ ai_review/tests/suites/services/llm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
203
+ ai_review/tests/suites/services/llm/test_factory.py,sha256=_i_UFtG_WGT3jpBDm20Hb0rFTFrfPuiFJhhSrlvUlVQ,1120
190
204
  ai_review/tests/suites/services/prompt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
191
205
  ai_review/tests/suites/services/prompt/test_adapter.py,sha256=9KZOFQmZUs3l_cW7Q5LIMPs4i4J-gOCQ6VrlDPR0ImU,2156
192
- ai_review/tests/suites/services/prompt/test_schema.py,sha256=DQyv5gUJ2VkxaD9wiKLS18ECopvvdKvF4sg3MTGcKs8,2547
206
+ ai_review/tests/suites/services/prompt/test_schema.py,sha256=rm2__LA2_4qQwSmNAZ_Wnpy11T3yYRkYUkRUrqxUQKE,5421
193
207
  ai_review/tests/suites/services/prompt/test_service.py,sha256=WXYKwDHMmWD6ew1awiEzmoxEJtQBqxvOgiyK8Ii9Mhw,6755
194
208
  ai_review/tests/suites/services/prompt/test_tools.py,sha256=_yNZoBATvPU5enWNIopbjY8lVVjfaB_46kNIKODhCW4,1981
195
209
  ai_review/tests/suites/services/review/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
196
- ai_review/tests/suites/services/review/test_service.py,sha256=Tcl-p9wtnIp4TjbE3bvoNesoDlArtWorcwpPEHKou6c,5609
210
+ ai_review/tests/suites/services/review/test_service.py,sha256=fCmTSb8bDPjvbORGpStz4YqqWqXBnvIQy_soJXPa1wQ,5690
197
211
  ai_review/tests/suites/services/review/inline/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
198
212
  ai_review/tests/suites/services/review/inline/test_schema.py,sha256=C5H6zqEHaf9OO4VHX0atYAt21CmOcCARaijSo-FUqj8,2368
199
213
  ai_review/tests/suites/services/review/inline/test_service.py,sha256=x8d-dhw_uEXtGVLDVv4xVodmscrXIfDkoAnG4UapdlQ,3815
@@ -202,9 +216,15 @@ ai_review/tests/suites/services/review/policy/test_service.py,sha256=kRWT550OjWY
202
216
  ai_review/tests/suites/services/review/summary/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
203
217
  ai_review/tests/suites/services/review/summary/test_schema.py,sha256=HUbSDbQzBp-iTsGLs7hJfu-sz6sq9xLO0woGmZPWyx0,735
204
218
  ai_review/tests/suites/services/review/summary/test_service.py,sha256=ibiYOWQMZuQKRutIT_EKGq7DEPQvp62YhscNHeSWFVQ,588
205
- xai_review-0.21.0.dist-info/licenses/LICENSE,sha256=p-v8m7Kmz4KKc7PcvsGiGEmCw9AiSXY4_ylOPy_u--Y,11343
206
- xai_review-0.21.0.dist-info/METADATA,sha256=N7BrGJd6tOk0p2rE7GZdTZXwrpBalyGY_iGdvUaatbM,10872
207
- xai_review-0.21.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
208
- xai_review-0.21.0.dist-info/entry_points.txt,sha256=JyC5URanMi5io5P_PXQf7H_I1OGIpk5cZQhaPQ0g4Zs,53
209
- xai_review-0.21.0.dist-info/top_level.txt,sha256=sTsZbfzLoqvRZKdKa-BcxWvjlHdrpbeJ6DrGY0EuR0E,10
210
- xai_review-0.21.0.dist-info/RECORD,,
219
+ ai_review/tests/suites/services/vcs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
220
+ ai_review/tests/suites/services/vcs/test_factory.py,sha256=RLxKRSISJQGH9_h2QY7zLvMyAVF4shYoEmKrrmUySME,850
221
+ ai_review/tests/suites/services/vcs/github/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
222
+ ai_review/tests/suites/services/vcs/github/test_service.py,sha256=c2sjecm4qzqYXuO9j6j35NQyJzqDpnXIJImRTcpkyHo,4378
223
+ ai_review/tests/suites/services/vcs/gitlab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
224
+ ai_review/tests/suites/services/vcs/gitlab/test_service.py,sha256=0dqgL5whzjcP-AQ4adP_12QfkYm_ZtdtMotmYm8Se7Y,4449
225
+ xai_review-0.23.0.dist-info/licenses/LICENSE,sha256=p-v8m7Kmz4KKc7PcvsGiGEmCw9AiSXY4_ylOPy_u--Y,11343
226
+ xai_review-0.23.0.dist-info/METADATA,sha256=6GjvVteV4O_MPSSgTB4dNhlbS7iNKlGO5Uei0Y6JAuQ,10872
227
+ xai_review-0.23.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
228
+ xai_review-0.23.0.dist-info/entry_points.txt,sha256=JyC5URanMi5io5P_PXQf7H_I1OGIpk5cZQhaPQ0g4Zs,53
229
+ xai_review-0.23.0.dist-info/top_level.txt,sha256=sTsZbfzLoqvRZKdKa-BcxWvjlHdrpbeJ6DrGY0EuR0E,10
230
+ xai_review-0.23.0.dist-info/RECORD,,
File without changes