xai-review 0.27.0__py3-none-any.whl → 0.28.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.
- ai_review/cli/commands/run_inline_reply_review.py +7 -0
- ai_review/cli/commands/run_summary_reply_review.py +7 -0
- ai_review/cli/main.py +17 -0
- ai_review/clients/bitbucket/pr/schema/comments.py +14 -0
- ai_review/clients/bitbucket/pr/schema/pull_request.py +1 -5
- ai_review/clients/bitbucket/pr/schema/user.py +7 -0
- ai_review/clients/github/pr/client.py +35 -4
- ai_review/clients/github/pr/schema/comments.py +21 -0
- ai_review/clients/github/pr/schema/pull_request.py +1 -4
- ai_review/clients/github/pr/schema/user.py +6 -0
- ai_review/clients/github/pr/types.py +11 -1
- ai_review/clients/gitlab/mr/client.py +32 -1
- ai_review/clients/gitlab/mr/schema/changes.py +1 -5
- ai_review/clients/gitlab/mr/schema/discussions.py +17 -7
- ai_review/clients/gitlab/mr/schema/notes.py +3 -0
- ai_review/clients/gitlab/mr/schema/user.py +7 -0
- ai_review/clients/gitlab/mr/types.py +16 -7
- ai_review/libs/config/prompt.py +96 -64
- ai_review/libs/config/review.py +2 -0
- ai_review/libs/llm/output_json_parser.py +60 -0
- ai_review/prompts/default_inline_reply.md +10 -0
- ai_review/prompts/default_summary_reply.md +14 -0
- ai_review/prompts/default_system_inline_reply.md +31 -0
- ai_review/prompts/default_system_summary_reply.md +13 -0
- ai_review/services/artifacts/schema.py +2 -2
- ai_review/services/hook/constants.py +14 -0
- ai_review/services/hook/service.py +95 -4
- ai_review/services/hook/types.py +18 -2
- ai_review/services/prompt/adapter.py +1 -1
- ai_review/services/prompt/service.py +49 -3
- ai_review/services/prompt/tools.py +21 -0
- ai_review/services/prompt/types.py +23 -0
- ai_review/services/review/gateway/comment.py +45 -6
- ai_review/services/review/gateway/llm.py +2 -1
- ai_review/services/review/gateway/types.py +50 -0
- ai_review/services/review/internal/inline/service.py +40 -0
- ai_review/services/review/internal/inline/types.py +8 -0
- ai_review/services/review/internal/inline_reply/schema.py +23 -0
- ai_review/services/review/internal/inline_reply/service.py +20 -0
- ai_review/services/review/internal/inline_reply/types.py +8 -0
- ai_review/services/review/{policy → internal/policy}/service.py +2 -1
- ai_review/services/review/internal/policy/types.py +15 -0
- ai_review/services/review/{summary → internal/summary}/service.py +2 -2
- ai_review/services/review/{summary → internal/summary}/types.py +1 -1
- ai_review/services/review/internal/summary_reply/__init__.py +0 -0
- ai_review/services/review/internal/summary_reply/schema.py +8 -0
- ai_review/services/review/internal/summary_reply/service.py +15 -0
- ai_review/services/review/internal/summary_reply/types.py +8 -0
- ai_review/services/review/runner/__init__.py +0 -0
- ai_review/services/review/runner/context.py +72 -0
- ai_review/services/review/runner/inline.py +80 -0
- ai_review/services/review/runner/inline_reply.py +80 -0
- ai_review/services/review/runner/summary.py +71 -0
- ai_review/services/review/runner/summary_reply.py +79 -0
- ai_review/services/review/runner/types.py +6 -0
- ai_review/services/review/service.py +78 -110
- ai_review/services/vcs/bitbucket/adapter.py +24 -0
- ai_review/services/vcs/bitbucket/client.py +107 -42
- ai_review/services/vcs/github/adapter.py +35 -0
- ai_review/services/vcs/github/client.py +105 -44
- ai_review/services/vcs/gitlab/adapter.py +26 -0
- ai_review/services/vcs/gitlab/client.py +91 -38
- ai_review/services/vcs/types.py +34 -0
- ai_review/tests/fixtures/clients/bitbucket.py +2 -2
- ai_review/tests/fixtures/clients/github.py +35 -6
- ai_review/tests/fixtures/clients/gitlab.py +42 -3
- ai_review/tests/fixtures/libs/__init__.py +0 -0
- ai_review/tests/fixtures/libs/llm/__init__.py +0 -0
- ai_review/tests/fixtures/libs/llm/output_json_parser.py +13 -0
- ai_review/tests/fixtures/services/hook.py +8 -0
- ai_review/tests/fixtures/services/llm.py +8 -5
- ai_review/tests/fixtures/services/prompt.py +70 -0
- ai_review/tests/fixtures/services/review/base.py +41 -0
- ai_review/tests/fixtures/services/review/gateway/__init__.py +0 -0
- ai_review/tests/fixtures/services/review/gateway/comment.py +98 -0
- ai_review/tests/fixtures/services/review/gateway/llm.py +17 -0
- ai_review/tests/fixtures/services/review/internal/__init__.py +0 -0
- ai_review/tests/fixtures/services/review/{inline.py → internal/inline.py} +8 -6
- ai_review/tests/fixtures/services/review/internal/inline_reply.py +25 -0
- ai_review/tests/fixtures/services/review/internal/policy.py +28 -0
- ai_review/tests/fixtures/services/review/internal/summary.py +21 -0
- ai_review/tests/fixtures/services/review/internal/summary_reply.py +19 -0
- ai_review/tests/fixtures/services/review/runner/__init__.py +0 -0
- ai_review/tests/fixtures/services/review/runner/context.py +50 -0
- ai_review/tests/fixtures/services/review/runner/inline.py +50 -0
- ai_review/tests/fixtures/services/review/runner/inline_reply.py +50 -0
- ai_review/tests/fixtures/services/review/runner/summary.py +50 -0
- ai_review/tests/fixtures/services/review/runner/summary_reply.py +50 -0
- ai_review/tests/fixtures/services/vcs.py +23 -0
- ai_review/tests/suites/cli/__init__.py +0 -0
- ai_review/tests/suites/cli/test_main.py +54 -0
- ai_review/tests/suites/libs/config/test_prompt.py +108 -28
- ai_review/tests/suites/libs/llm/__init__.py +0 -0
- ai_review/tests/suites/libs/llm/test_output_json_parser.py +155 -0
- ai_review/tests/suites/services/hook/test_service.py +88 -4
- ai_review/tests/suites/services/prompt/test_adapter.py +3 -3
- ai_review/tests/suites/services/prompt/test_service.py +102 -58
- ai_review/tests/suites/services/prompt/test_tools.py +86 -1
- ai_review/tests/suites/services/review/gateway/__init__.py +0 -0
- ai_review/tests/suites/services/review/gateway/test_comment.py +253 -0
- ai_review/tests/suites/services/review/gateway/test_llm.py +82 -0
- ai_review/tests/suites/services/review/internal/__init__.py +0 -0
- ai_review/tests/suites/services/review/internal/inline/__init__.py +0 -0
- ai_review/tests/suites/services/review/{inline → internal/inline}/test_schema.py +1 -1
- ai_review/tests/suites/services/review/internal/inline/test_service.py +81 -0
- ai_review/tests/suites/services/review/internal/inline_reply/__init__.py +0 -0
- ai_review/tests/suites/services/review/internal/inline_reply/test_schema.py +57 -0
- ai_review/tests/suites/services/review/internal/inline_reply/test_service.py +72 -0
- ai_review/tests/suites/services/review/internal/policy/__init__.py +0 -0
- ai_review/tests/suites/services/review/{policy → internal/policy}/test_service.py +1 -1
- ai_review/tests/suites/services/review/internal/summary/__init__.py +0 -0
- ai_review/tests/suites/services/review/{summary → internal/summary}/test_schema.py +1 -1
- ai_review/tests/suites/services/review/{summary → internal/summary}/test_service.py +2 -2
- ai_review/tests/suites/services/review/internal/summary_reply/__init__.py +0 -0
- ai_review/tests/suites/services/review/internal/summary_reply/test_schema.py +19 -0
- ai_review/tests/suites/services/review/internal/summary_reply/test_service.py +21 -0
- ai_review/tests/suites/services/review/runner/__init__.py +0 -0
- ai_review/tests/suites/services/review/runner/test_context.py +89 -0
- ai_review/tests/suites/services/review/runner/test_inline.py +100 -0
- ai_review/tests/suites/services/review/runner/test_inline_reply.py +109 -0
- ai_review/tests/suites/services/review/runner/test_summary.py +87 -0
- ai_review/tests/suites/services/review/runner/test_summary_reply.py +97 -0
- ai_review/tests/suites/services/review/test_service.py +64 -97
- ai_review/tests/suites/services/vcs/bitbucket/test_adapter.py +109 -0
- ai_review/tests/suites/services/vcs/bitbucket/{test_service.py → test_client.py} +88 -1
- ai_review/tests/suites/services/vcs/github/test_adapter.py +162 -0
- ai_review/tests/suites/services/vcs/github/{test_service.py → test_client.py} +102 -2
- ai_review/tests/suites/services/vcs/gitlab/test_adapter.py +105 -0
- ai_review/tests/suites/services/vcs/gitlab/{test_service.py → test_client.py} +99 -1
- {xai_review-0.27.0.dist-info → xai_review-0.28.0.dist-info}/METADATA +8 -5
- {xai_review-0.27.0.dist-info → xai_review-0.28.0.dist-info}/RECORD +143 -70
- ai_review/services/review/inline/service.py +0 -54
- ai_review/services/review/inline/types.py +0 -11
- ai_review/tests/fixtures/services/review/summary.py +0 -19
- ai_review/tests/suites/services/review/inline/test_service.py +0 -107
- /ai_review/{services/review/inline → libs/llm}/__init__.py +0 -0
- /ai_review/services/review/{policy → internal}/__init__.py +0 -0
- /ai_review/services/review/{summary → internal/inline}/__init__.py +0 -0
- /ai_review/services/review/{inline → internal/inline}/schema.py +0 -0
- /ai_review/{tests/suites/services/review/inline → services/review/internal/inline_reply}/__init__.py +0 -0
- /ai_review/{tests/suites/services/review → services/review/internal}/policy/__init__.py +0 -0
- /ai_review/{tests/suites/services/review → services/review/internal}/summary/__init__.py +0 -0
- /ai_review/services/review/{summary → internal/summary}/schema.py +0 -0
- {xai_review-0.27.0.dist-info → xai_review-0.28.0.dist-info}/WHEEL +0 -0
- {xai_review-0.27.0.dist-info → xai_review-0.28.0.dist-info}/entry_points.txt +0 -0
- {xai_review-0.27.0.dist-info → xai_review-0.28.0.dist-info}/licenses/LICENSE +0 -0
- {xai_review-0.27.0.dist-info → xai_review-0.28.0.dist-info}/top_level.txt +0 -0
ai_review/cli/main.py
CHANGED
|
@@ -3,8 +3,10 @@ import asyncio
|
|
|
3
3
|
import typer
|
|
4
4
|
|
|
5
5
|
from ai_review.cli.commands.run_context_review import run_context_review_command
|
|
6
|
+
from ai_review.cli.commands.run_inline_reply_review import run_inline_reply_review_command
|
|
6
7
|
from ai_review.cli.commands.run_inline_review import run_inline_review_command
|
|
7
8
|
from ai_review.cli.commands.run_review import run_review_command
|
|
9
|
+
from ai_review.cli.commands.run_summary_reply_review import run_summary_reply_review_command
|
|
8
10
|
from ai_review.cli.commands.run_summary_review import run_summary_review_command
|
|
9
11
|
from ai_review.config import settings
|
|
10
12
|
|
|
@@ -43,6 +45,21 @@ def run_summary():
|
|
|
43
45
|
typer.secho("AI review completed successfully!", fg=typer.colors.GREEN, bold=True)
|
|
44
46
|
|
|
45
47
|
|
|
48
|
+
@app.command("run-inline-reply")
|
|
49
|
+
def run_inline_reply():
|
|
50
|
+
"""Run only the inline reply review"""
|
|
51
|
+
typer.secho("Starting inline reply AI review...", fg=typer.colors.CYAN)
|
|
52
|
+
asyncio.run(run_inline_reply_review_command())
|
|
53
|
+
typer.secho("AI review completed successfully!", fg=typer.colors.GREEN, bold=True)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@app.command("run-summary-reply")
|
|
57
|
+
def run_summary_reply():
|
|
58
|
+
typer.secho("Starting summary reply AI review...", fg=typer.colors.CYAN)
|
|
59
|
+
asyncio.run(run_summary_reply_review_command())
|
|
60
|
+
typer.secho("AI review completed successfully!", fg=typer.colors.GREEN, bold=True)
|
|
61
|
+
|
|
62
|
+
|
|
46
63
|
@app.command("show-config")
|
|
47
64
|
def show_config():
|
|
48
65
|
"""Show the current resolved configuration"""
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from pydantic import BaseModel, Field, ConfigDict
|
|
2
2
|
|
|
3
|
+
from ai_review.clients.bitbucket.pr.schema.user import BitbucketUserSchema
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
class BitbucketCommentContentSchema(BaseModel):
|
|
5
7
|
raw: str
|
|
@@ -15,8 +17,14 @@ class BitbucketCommentInlineSchema(BaseModel):
|
|
|
15
17
|
from_line: int | None = Field(alias="from", default=None)
|
|
16
18
|
|
|
17
19
|
|
|
20
|
+
class BitbucketCommentParentSchema(BaseModel):
|
|
21
|
+
id: int
|
|
22
|
+
|
|
23
|
+
|
|
18
24
|
class BitbucketPRCommentSchema(BaseModel):
|
|
19
25
|
id: int
|
|
26
|
+
user: BitbucketUserSchema | None = None
|
|
27
|
+
parent: BitbucketCommentParentSchema | None = None
|
|
20
28
|
inline: BitbucketCommentInlineSchema | None = None
|
|
21
29
|
content: BitbucketCommentContentSchema
|
|
22
30
|
|
|
@@ -38,12 +46,18 @@ class BitbucketGetPRCommentsResponseSchema(BaseModel):
|
|
|
38
46
|
page_len: int = Field(alias="pagelen")
|
|
39
47
|
|
|
40
48
|
|
|
49
|
+
class BitbucketParentSchema(BaseModel):
|
|
50
|
+
id: int
|
|
51
|
+
|
|
52
|
+
|
|
41
53
|
class BitbucketCreatePRCommentRequestSchema(BaseModel):
|
|
54
|
+
parent: BitbucketParentSchema | None = None
|
|
42
55
|
inline: BitbucketCommentInlineSchema | None = None
|
|
43
56
|
content: BitbucketCommentContentSchema
|
|
44
57
|
|
|
45
58
|
|
|
46
59
|
class BitbucketCreatePRCommentResponseSchema(BaseModel):
|
|
47
60
|
id: int
|
|
61
|
+
parent: BitbucketParentSchema | None = None
|
|
48
62
|
inline: BitbucketCommentInlineSchema | None = None
|
|
49
63
|
content: BitbucketCommentContentSchema
|
|
@@ -2,10 +2,13 @@ from httpx import Response, QueryParams
|
|
|
2
2
|
|
|
3
3
|
from ai_review.clients.github.pr.schema.comments import (
|
|
4
4
|
GitHubPRCommentSchema,
|
|
5
|
+
GitHubIssueCommentSchema,
|
|
5
6
|
GitHubGetPRCommentsQuerySchema,
|
|
6
7
|
GitHubGetPRCommentsResponseSchema,
|
|
8
|
+
GitHubGetIssueCommentsResponseSchema,
|
|
7
9
|
GitHubCreateIssueCommentRequestSchema,
|
|
8
10
|
GitHubCreateIssueCommentResponseSchema,
|
|
11
|
+
GitHubCreateReviewReplyRequestSchema,
|
|
9
12
|
GitHubCreateReviewCommentRequestSchema,
|
|
10
13
|
GitHubCreateReviewCommentResponseSchema
|
|
11
14
|
)
|
|
@@ -76,6 +79,19 @@ class GitHubPullRequestsHTTPClient(HTTPClient, GitHubPullRequestsHTTPClientProto
|
|
|
76
79
|
query=QueryParams(**query.model_dump())
|
|
77
80
|
)
|
|
78
81
|
|
|
82
|
+
@handle_http_error(client="GitHubPullRequestsHTTPClient", exception=GitHubPullRequestsHTTPClientError)
|
|
83
|
+
async def create_review_reply_api(
|
|
84
|
+
self,
|
|
85
|
+
owner: str,
|
|
86
|
+
repo: str,
|
|
87
|
+
pull_number: str,
|
|
88
|
+
request: GitHubCreateReviewReplyRequestSchema,
|
|
89
|
+
) -> Response:
|
|
90
|
+
return await self.post(
|
|
91
|
+
f"/repos/{owner}/{repo}/pulls/{pull_number}/comments",
|
|
92
|
+
json=request.model_dump(),
|
|
93
|
+
)
|
|
94
|
+
|
|
79
95
|
@handle_http_error(client="GitHubPullRequestsHTTPClient", exception=GitHubPullRequestsHTTPClientError)
|
|
80
96
|
async def create_review_comment_api(
|
|
81
97
|
self,
|
|
@@ -136,13 +152,18 @@ class GitHubPullRequestsHTTPClient(HTTPClient, GitHubPullRequestsHTTPClientProto
|
|
|
136
152
|
)
|
|
137
153
|
return GitHubGetPRFilesResponseSchema(root=items)
|
|
138
154
|
|
|
139
|
-
async def get_issue_comments(
|
|
155
|
+
async def get_issue_comments(
|
|
156
|
+
self,
|
|
157
|
+
owner: str,
|
|
158
|
+
repo: str,
|
|
159
|
+
issue_number: str
|
|
160
|
+
) -> GitHubGetIssueCommentsResponseSchema:
|
|
140
161
|
async def fetch_page(page: int) -> Response:
|
|
141
162
|
query = GitHubGetPRCommentsQuerySchema(page=page, per_page=settings.vcs.pagination.per_page)
|
|
142
163
|
return await self.get_issue_comments_api(owner, repo, issue_number, query)
|
|
143
164
|
|
|
144
|
-
def extract_items(response: Response) -> list[
|
|
145
|
-
result =
|
|
165
|
+
def extract_items(response: Response) -> list[GitHubIssueCommentSchema]:
|
|
166
|
+
result = GitHubGetIssueCommentsResponseSchema.model_validate_json(response.text)
|
|
146
167
|
return result.root
|
|
147
168
|
|
|
148
169
|
items = await paginate(
|
|
@@ -151,7 +172,7 @@ class GitHubPullRequestsHTTPClient(HTTPClient, GitHubPullRequestsHTTPClientProto
|
|
|
151
172
|
extract_items=extract_items,
|
|
152
173
|
has_next_page=github_has_next_page
|
|
153
174
|
)
|
|
154
|
-
return
|
|
175
|
+
return GitHubGetIssueCommentsResponseSchema(root=items)
|
|
155
176
|
|
|
156
177
|
async def get_review_comments(self, owner: str, repo: str, pull_number: str) -> GitHubGetPRCommentsResponseSchema:
|
|
157
178
|
async def fetch_page(page: int) -> Response:
|
|
@@ -187,6 +208,16 @@ class GitHubPullRequestsHTTPClient(HTTPClient, GitHubPullRequestsHTTPClientProto
|
|
|
187
208
|
)
|
|
188
209
|
return GitHubGetPRReviewsResponseSchema(root=items)
|
|
189
210
|
|
|
211
|
+
async def create_review_reply(
|
|
212
|
+
self,
|
|
213
|
+
owner: str,
|
|
214
|
+
repo: str,
|
|
215
|
+
pull_number: str,
|
|
216
|
+
request: GitHubCreateReviewReplyRequestSchema,
|
|
217
|
+
) -> GitHubCreateReviewCommentResponseSchema:
|
|
218
|
+
response = await self.create_review_reply_api(owner, repo, pull_number, request)
|
|
219
|
+
return GitHubCreateReviewCommentResponseSchema.model_validate_json(response.text)
|
|
220
|
+
|
|
190
221
|
async def create_review_comment(
|
|
191
222
|
self,
|
|
192
223
|
owner: str,
|
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
from pydantic import BaseModel, RootModel
|
|
2
2
|
|
|
3
|
+
from ai_review.clients.github.pr.schema.user import GitHubUserSchema
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class GitHubIssueCommentSchema(BaseModel):
|
|
7
|
+
"""Represents a top-level comment in a PR discussion (issue-level)."""
|
|
8
|
+
id: int
|
|
9
|
+
body: str
|
|
10
|
+
user: GitHubUserSchema | None = None
|
|
11
|
+
|
|
3
12
|
|
|
4
13
|
class GitHubPRCommentSchema(BaseModel):
|
|
14
|
+
"""Represents an inline code review comment on a specific line in a PR."""
|
|
5
15
|
id: int
|
|
6
16
|
body: str
|
|
7
17
|
path: str | None = None
|
|
8
18
|
line: int | None = None
|
|
19
|
+
user: GitHubUserSchema | None = None
|
|
20
|
+
in_reply_to_id: int | None = None
|
|
9
21
|
|
|
10
22
|
|
|
11
23
|
class GitHubGetPRCommentsQuerySchema(BaseModel):
|
|
@@ -17,6 +29,10 @@ class GitHubGetPRCommentsResponseSchema(RootModel[list[GitHubPRCommentSchema]]):
|
|
|
17
29
|
root: list[GitHubPRCommentSchema]
|
|
18
30
|
|
|
19
31
|
|
|
32
|
+
class GitHubGetIssueCommentsResponseSchema(RootModel[list[GitHubIssueCommentSchema]]):
|
|
33
|
+
root: list[GitHubIssueCommentSchema]
|
|
34
|
+
|
|
35
|
+
|
|
20
36
|
class GitHubCreateIssueCommentRequestSchema(BaseModel):
|
|
21
37
|
body: str
|
|
22
38
|
|
|
@@ -26,6 +42,11 @@ class GitHubCreateIssueCommentResponseSchema(BaseModel):
|
|
|
26
42
|
body: str
|
|
27
43
|
|
|
28
44
|
|
|
45
|
+
class GitHubCreateReviewReplyRequestSchema(BaseModel):
|
|
46
|
+
body: str
|
|
47
|
+
in_reply_to: int
|
|
48
|
+
|
|
49
|
+
|
|
29
50
|
class GitHubCreateReviewCommentRequestSchema(BaseModel):
|
|
30
51
|
body: str
|
|
31
52
|
path: str
|
|
@@ -2,7 +2,9 @@ from typing import Protocol
|
|
|
2
2
|
|
|
3
3
|
from ai_review.clients.github.pr.schema.comments import (
|
|
4
4
|
GitHubGetPRCommentsResponseSchema,
|
|
5
|
+
GitHubGetIssueCommentsResponseSchema,
|
|
5
6
|
GitHubCreateIssueCommentResponseSchema,
|
|
7
|
+
GitHubCreateReviewReplyRequestSchema,
|
|
6
8
|
GitHubCreateReviewCommentResponseSchema,
|
|
7
9
|
GitHubCreateReviewCommentRequestSchema,
|
|
8
10
|
)
|
|
@@ -21,7 +23,7 @@ class GitHubPullRequestsHTTPClientProtocol(Protocol):
|
|
|
21
23
|
owner: str,
|
|
22
24
|
repo: str,
|
|
23
25
|
issue_number: str
|
|
24
|
-
) ->
|
|
26
|
+
) -> GitHubGetIssueCommentsResponseSchema: ...
|
|
25
27
|
|
|
26
28
|
async def get_review_comments(
|
|
27
29
|
self,
|
|
@@ -32,6 +34,14 @@ class GitHubPullRequestsHTTPClientProtocol(Protocol):
|
|
|
32
34
|
|
|
33
35
|
async def get_reviews(self, owner: str, repo: str, pull_number: str) -> GitHubGetPRReviewsResponseSchema: ...
|
|
34
36
|
|
|
37
|
+
async def create_review_reply(
|
|
38
|
+
self,
|
|
39
|
+
owner: str,
|
|
40
|
+
repo: str,
|
|
41
|
+
comment_id: str,
|
|
42
|
+
request: GitHubCreateReviewReplyRequestSchema,
|
|
43
|
+
) -> GitHubCreateReviewCommentResponseSchema: ...
|
|
44
|
+
|
|
35
45
|
async def create_review_comment(
|
|
36
46
|
self,
|
|
37
47
|
owner: str,
|
|
@@ -6,7 +6,9 @@ from ai_review.clients.gitlab.mr.schema.discussions import (
|
|
|
6
6
|
GitLabGetMRDiscussionsQuerySchema,
|
|
7
7
|
GitLabGetMRDiscussionsResponseSchema,
|
|
8
8
|
GitLabCreateMRDiscussionRequestSchema,
|
|
9
|
-
GitLabCreateMRDiscussionResponseSchema
|
|
9
|
+
GitLabCreateMRDiscussionResponseSchema,
|
|
10
|
+
GitLabCreateMRDiscussionReplyRequestSchema,
|
|
11
|
+
GitLabCreateMRDiscussionReplyResponseSchema
|
|
10
12
|
)
|
|
11
13
|
from ai_review.clients.gitlab.mr.schema.notes import (
|
|
12
14
|
GitLabNoteSchema,
|
|
@@ -82,6 +84,19 @@ class GitLabMergeRequestsHTTPClient(HTTPClient, GitLabMergeRequestsHTTPClientPro
|
|
|
82
84
|
json=request.model_dump(),
|
|
83
85
|
)
|
|
84
86
|
|
|
87
|
+
@handle_http_error(client="GitLabMergeRequestsHTTPClient", exception=GitLabMergeRequestsHTTPClientError)
|
|
88
|
+
async def create_discussion_reply_api(
|
|
89
|
+
self,
|
|
90
|
+
project_id: str,
|
|
91
|
+
merge_request_id: str,
|
|
92
|
+
discussion_id: str,
|
|
93
|
+
request: GitLabCreateMRDiscussionReplyRequestSchema,
|
|
94
|
+
) -> Response:
|
|
95
|
+
return await self.post(
|
|
96
|
+
f"/api/v4/projects/{project_id}/merge_requests/{merge_request_id}/discussions/{discussion_id}/notes",
|
|
97
|
+
json=request.model_dump(),
|
|
98
|
+
)
|
|
99
|
+
|
|
85
100
|
async def get_changes(self, project_id: str, merge_request_id: str) -> GitLabGetMRChangesResponseSchema:
|
|
86
101
|
response = await self.get_changes_api(project_id, merge_request_id)
|
|
87
102
|
return GitLabGetMRChangesResponseSchema.model_validate_json(response.text)
|
|
@@ -154,3 +169,19 @@ class GitLabMergeRequestsHTTPClient(HTTPClient, GitLabMergeRequestsHTTPClientPro
|
|
|
154
169
|
merge_request_id=merge_request_id
|
|
155
170
|
)
|
|
156
171
|
return GitLabCreateMRDiscussionResponseSchema.model_validate_json(response.text)
|
|
172
|
+
|
|
173
|
+
async def create_discussion_reply(
|
|
174
|
+
self,
|
|
175
|
+
project_id: str,
|
|
176
|
+
merge_request_id: str,
|
|
177
|
+
discussion_id: str,
|
|
178
|
+
body: str,
|
|
179
|
+
) -> GitLabCreateMRDiscussionReplyResponseSchema:
|
|
180
|
+
request = GitLabCreateMRDiscussionReplyRequestSchema(body=body)
|
|
181
|
+
response = await self.create_discussion_reply_api(
|
|
182
|
+
project_id=project_id,
|
|
183
|
+
merge_request_id=merge_request_id,
|
|
184
|
+
discussion_id=discussion_id,
|
|
185
|
+
request=request,
|
|
186
|
+
)
|
|
187
|
+
return GitLabCreateMRDiscussionReplyResponseSchema.model_validate_json(response.text)
|
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
from pydantic import BaseModel, RootModel
|
|
1
|
+
from pydantic import BaseModel, RootModel, Field
|
|
2
2
|
|
|
3
3
|
from ai_review.clients.gitlab.mr.schema.notes import GitLabNoteSchema
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
class GitLabDiscussionSchema(BaseModel):
|
|
7
|
-
id: str
|
|
8
|
-
notes: list[GitLabNoteSchema]
|
|
9
|
-
|
|
10
|
-
|
|
11
6
|
class GitLabDiscussionPositionSchema(BaseModel):
|
|
12
7
|
position_type: str = "text"
|
|
13
8
|
base_sha: str
|
|
@@ -17,6 +12,12 @@ class GitLabDiscussionPositionSchema(BaseModel):
|
|
|
17
12
|
new_line: int
|
|
18
13
|
|
|
19
14
|
|
|
15
|
+
class GitLabDiscussionSchema(BaseModel):
|
|
16
|
+
id: str
|
|
17
|
+
notes: list[GitLabNoteSchema]
|
|
18
|
+
position: GitLabDiscussionPositionSchema | None = None
|
|
19
|
+
|
|
20
|
+
|
|
20
21
|
class GitLabGetMRDiscussionsQuerySchema(BaseModel):
|
|
21
22
|
page: int = 1
|
|
22
23
|
per_page: int = 100
|
|
@@ -33,4 +34,13 @@ class GitLabCreateMRDiscussionRequestSchema(BaseModel):
|
|
|
33
34
|
|
|
34
35
|
class GitLabCreateMRDiscussionResponseSchema(BaseModel):
|
|
35
36
|
id: str
|
|
36
|
-
|
|
37
|
+
notes: list[GitLabNoteSchema] = Field(default_factory=list)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class GitLabCreateMRDiscussionReplyRequestSchema(BaseModel):
|
|
41
|
+
body: str
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class GitLabCreateMRDiscussionReplyResponseSchema(BaseModel):
|
|
45
|
+
id: int
|
|
46
|
+
body: str
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
from pydantic import BaseModel, RootModel
|
|
2
2
|
|
|
3
|
+
from ai_review.clients.gitlab.mr.schema.user import GitLabUserSchema
|
|
4
|
+
|
|
3
5
|
|
|
4
6
|
class GitLabNoteSchema(BaseModel):
|
|
5
7
|
id: int
|
|
6
8
|
body: str
|
|
9
|
+
author: GitLabUserSchema | None = None
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
class GitLabGetMRNotesQuerySchema(BaseModel):
|
|
@@ -3,8 +3,9 @@ from typing import Protocol
|
|
|
3
3
|
from ai_review.clients.gitlab.mr.schema.changes import GitLabGetMRChangesResponseSchema
|
|
4
4
|
from ai_review.clients.gitlab.mr.schema.discussions import (
|
|
5
5
|
GitLabGetMRDiscussionsResponseSchema,
|
|
6
|
-
GitLabCreateMRDiscussionResponseSchema,
|
|
7
6
|
GitLabCreateMRDiscussionRequestSchema,
|
|
7
|
+
GitLabCreateMRDiscussionResponseSchema,
|
|
8
|
+
GitLabCreateMRDiscussionReplyResponseSchema
|
|
8
9
|
)
|
|
9
10
|
from ai_review.clients.gitlab.mr.schema.notes import GitLabGetMRNotesResponseSchema, GitLabCreateMRNoteResponseSchema
|
|
10
11
|
|
|
@@ -14,12 +15,6 @@ class GitLabMergeRequestsHTTPClientProtocol(Protocol):
|
|
|
14
15
|
|
|
15
16
|
async def get_notes(self, project_id: str, merge_request_id: str) -> GitLabGetMRNotesResponseSchema: ...
|
|
16
17
|
|
|
17
|
-
async def get_discussions(
|
|
18
|
-
self,
|
|
19
|
-
project_id: str,
|
|
20
|
-
merge_request_id: str
|
|
21
|
-
) -> GitLabGetMRDiscussionsResponseSchema: ...
|
|
22
|
-
|
|
23
18
|
async def create_note(
|
|
24
19
|
self,
|
|
25
20
|
body: str,
|
|
@@ -27,9 +22,23 @@ class GitLabMergeRequestsHTTPClientProtocol(Protocol):
|
|
|
27
22
|
merge_request_id: str,
|
|
28
23
|
) -> GitLabCreateMRNoteResponseSchema: ...
|
|
29
24
|
|
|
25
|
+
async def get_discussions(
|
|
26
|
+
self,
|
|
27
|
+
project_id: str,
|
|
28
|
+
merge_request_id: str
|
|
29
|
+
) -> GitLabGetMRDiscussionsResponseSchema: ...
|
|
30
|
+
|
|
30
31
|
async def create_discussion(
|
|
31
32
|
self,
|
|
32
33
|
project_id: str,
|
|
33
34
|
merge_request_id: str,
|
|
34
35
|
request: GitLabCreateMRDiscussionRequestSchema,
|
|
35
36
|
) -> GitLabCreateMRDiscussionResponseSchema: ...
|
|
37
|
+
|
|
38
|
+
async def create_discussion_reply(
|
|
39
|
+
self,
|
|
40
|
+
project_id: str,
|
|
41
|
+
merge_request_id: str,
|
|
42
|
+
discussion_id: str,
|
|
43
|
+
body: str,
|
|
44
|
+
) -> GitLabCreateMRDiscussionReplyResponseSchema: ...
|