xai-review 0.5.0__py3-none-any.whl → 0.6.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/libs/config/prompt.py +1 -0
- ai_review/libs/template/__init__.py +0 -0
- ai_review/libs/template/render.py +13 -0
- ai_review/services/prompt/schema.py +26 -45
- ai_review/tests/suites/clients/gitlab/__init__.py +0 -0
- ai_review/tests/suites/clients/gitlab/test_client.py +35 -0
- ai_review/tests/suites/libs/config/__init__.py +0 -0
- ai_review/tests/suites/libs/config/test_prompt.py +57 -0
- ai_review/tests/suites/libs/template/__init__.py +0 -0
- ai_review/tests/suites/libs/template/test_render.py +64 -0
- ai_review/tests/suites/services/prompt/test_schema.py +39 -6
- {xai_review-0.5.0.dist-info → xai_review-0.6.0.dist-info}/METADATA +25 -6
- {xai_review-0.5.0.dist-info → xai_review-0.6.0.dist-info}/RECORD +17 -9
- {xai_review-0.5.0.dist-info → xai_review-0.6.0.dist-info}/WHEEL +0 -0
- {xai_review-0.5.0.dist-info → xai_review-0.6.0.dist-info}/entry_points.txt +0 -0
- {xai_review-0.5.0.dist-info → xai_review-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {xai_review-0.5.0.dist-info → xai_review-0.6.0.dist-info}/top_level.txt +0 -0
ai_review/libs/config/prompt.py
CHANGED
|
@@ -8,6 +8,7 @@ from ai_review.libs.resources import load_resource
|
|
|
8
8
|
|
|
9
9
|
class PromptConfig(BaseModel):
|
|
10
10
|
context: dict[str, str] = Field(default_factory=dict)
|
|
11
|
+
context_placeholder: str = "<<{value}>>"
|
|
11
12
|
inline_prompt_files: list[FilePath] | None = None
|
|
12
13
|
context_prompt_files: list[FilePath] | None = None
|
|
13
14
|
summary_prompt_files: list[FilePath] | None = None
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Mapping
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def render_template(text: str, values: Mapping[str, str], placeholder: str = "<<{value}>>") -> str:
|
|
6
|
+
regex_pattern = re.escape(placeholder).replace(r"\{value\}", r"([\w\.-]+)")
|
|
7
|
+
regex = re.compile(regex_pattern)
|
|
8
|
+
|
|
9
|
+
def replacer(match: re.Match) -> str:
|
|
10
|
+
key = match.group(1)
|
|
11
|
+
return values.get(key, match.group(0))
|
|
12
|
+
|
|
13
|
+
return regex.sub(replacer, text)
|
|
@@ -1,71 +1,52 @@
|
|
|
1
1
|
from pydantic import BaseModel, Field
|
|
2
2
|
|
|
3
3
|
from ai_review.config import settings
|
|
4
|
+
from ai_review.libs.template.render import render_template
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class PromptContextSchema(BaseModel):
|
|
7
|
-
merge_request_title: str
|
|
8
|
-
merge_request_description: str
|
|
8
|
+
merge_request_title: str = ""
|
|
9
|
+
merge_request_description: str = ""
|
|
9
10
|
|
|
10
|
-
merge_request_author_name: str
|
|
11
|
-
merge_request_author_username: str
|
|
11
|
+
merge_request_author_name: str = ""
|
|
12
|
+
merge_request_author_username: str = ""
|
|
12
13
|
|
|
13
|
-
merge_request_reviewer: str
|
|
14
|
+
merge_request_reviewer: str = ""
|
|
14
15
|
merge_request_reviewers: list[str] = Field(default_factory=list)
|
|
15
16
|
merge_request_reviewers_usernames: list[str] = Field(default_factory=list)
|
|
16
17
|
|
|
17
18
|
merge_request_assignees: list[str] = Field(default_factory=list)
|
|
18
19
|
merge_request_assignees_usernames: list[str] = Field(default_factory=list)
|
|
19
20
|
|
|
20
|
-
source_branch: str
|
|
21
|
-
target_branch: str
|
|
21
|
+
source_branch: str = ""
|
|
22
|
+
target_branch: str = ""
|
|
22
23
|
|
|
23
24
|
labels: list[str] = Field(default_factory=list)
|
|
24
25
|
changed_files: list[str] = Field(default_factory=list)
|
|
25
26
|
|
|
26
27
|
@property
|
|
27
|
-
def
|
|
28
|
-
return
|
|
28
|
+
def render_values(self) -> dict[str, str]:
|
|
29
|
+
return {
|
|
30
|
+
"merge_request_title": self.merge_request_title,
|
|
31
|
+
"merge_request_description": self.merge_request_description,
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return ", ".join(self.merge_request_reviewers_usernames)
|
|
33
|
+
"merge_request_author_name": self.merge_request_author_name,
|
|
34
|
+
"merge_request_author_username": self.merge_request_author_username,
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
"merge_request_reviewer": self.merge_request_reviewer,
|
|
37
|
+
"merge_request_reviewers": ", ".join(self.merge_request_reviewers),
|
|
38
|
+
"merge_request_reviewers_usernames": ", ".join(self.merge_request_reviewers_usernames),
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return ", ".join(self.merge_request_assignees_usernames)
|
|
40
|
+
"merge_request_assignees": ", ".join(self.merge_request_assignees),
|
|
41
|
+
"merge_request_assignees_usernames": ", ".join(self.merge_request_assignees_usernames),
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return ", ".join(self.labels)
|
|
43
|
+
"source_branch": self.source_branch,
|
|
44
|
+
"target_branch": self.target_branch,
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
"labels": ", ".join(self.labels),
|
|
47
|
+
"changed_files": ", ".join(self.changed_files),
|
|
48
|
+
}
|
|
49
49
|
|
|
50
50
|
def apply_format(self, prompt: str) -> str:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
merge_request_description=self.merge_request_description or "",
|
|
54
|
-
|
|
55
|
-
merge_request_author_name=self.merge_request_author_name or "",
|
|
56
|
-
merge_request_author_username=self.merge_request_author_username or "",
|
|
57
|
-
|
|
58
|
-
merge_request_reviewer=self.merge_request_reviewer or "",
|
|
59
|
-
merge_request_reviewers=self.reviewers_format,
|
|
60
|
-
merge_request_reviewers_usernames=self.reviewers_usernames_format,
|
|
61
|
-
|
|
62
|
-
merge_request_assignees=self.assignees_format,
|
|
63
|
-
merge_request_assignees_usernames=self.assignees_usernames_format,
|
|
64
|
-
|
|
65
|
-
source_branch=self.source_branch or "",
|
|
66
|
-
target_branch=self.target_branch or "",
|
|
67
|
-
|
|
68
|
-
labels=self.labels_format,
|
|
69
|
-
changed_files=self.changed_files_format,
|
|
70
|
-
**settings.prompt.context
|
|
71
|
-
)
|
|
51
|
+
values = {**self.render_values, **settings.prompt.context}
|
|
52
|
+
return render_template(prompt, values, settings.prompt.context_placeholder)
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from httpx import AsyncClient
|
|
3
|
+
from pydantic import HttpUrl, SecretStr
|
|
4
|
+
|
|
5
|
+
from ai_review.clients.gitlab.client import get_gitlab_http_client, GitLabHTTPClient
|
|
6
|
+
from ai_review.clients.gitlab.mr.client import GitLabMergeRequestsHTTPClient
|
|
7
|
+
from ai_review.config import settings
|
|
8
|
+
from ai_review.libs.config.gitlab import GitLabPipelineConfig, GitLabHTTPClientConfig
|
|
9
|
+
from ai_review.libs.config.vcs import GitLabVCSConfig
|
|
10
|
+
from ai_review.libs.constants.vcs_provider import VCSProvider
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.fixture(autouse=True)
|
|
14
|
+
def gitlab_http_client_config(monkeypatch: pytest.MonkeyPatch):
|
|
15
|
+
fake_config = GitLabVCSConfig(
|
|
16
|
+
provider=VCSProvider.GITLAB,
|
|
17
|
+
pipeline=GitLabPipelineConfig(
|
|
18
|
+
project_id="project-id",
|
|
19
|
+
merge_request_id="merge-request-id"
|
|
20
|
+
),
|
|
21
|
+
http_client=GitLabHTTPClientConfig(
|
|
22
|
+
timeout=10,
|
|
23
|
+
api_url=HttpUrl("https://gitlab.com"),
|
|
24
|
+
api_token=SecretStr("fake-token"),
|
|
25
|
+
)
|
|
26
|
+
)
|
|
27
|
+
monkeypatch.setattr(settings, "vcs", fake_config)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def test_get_gitlab_http_client_builds_ok():
|
|
31
|
+
gitlab_http_client = get_gitlab_http_client()
|
|
32
|
+
|
|
33
|
+
assert isinstance(gitlab_http_client, GitLabHTTPClient)
|
|
34
|
+
assert isinstance(gitlab_http_client.mr, GitLabMergeRequestsHTTPClient)
|
|
35
|
+
assert isinstance(gitlab_http_client.mr.client, AsyncClient)
|
|
File without changes
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from ai_review.libs.config.prompt import PromptConfig
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_inline_prompt_files_or_default_uses_defaults(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
|
|
9
|
+
dummy_file = tmp_path / "dummy.md"
|
|
10
|
+
dummy_file.write_text("DUMMY")
|
|
11
|
+
monkeypatch.setattr("ai_review.libs.config.prompt.load_resource", lambda **_: dummy_file)
|
|
12
|
+
|
|
13
|
+
config = PromptConfig()
|
|
14
|
+
result = config.inline_prompt_files_or_default
|
|
15
|
+
|
|
16
|
+
assert result == [dummy_file]
|
|
17
|
+
assert config.load_inline() == ["DUMMY"]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_system_inline_prompts_none_returns_global(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
|
|
21
|
+
dummy_file = tmp_path / "global.md"
|
|
22
|
+
dummy_file.write_text("GLOBAL")
|
|
23
|
+
monkeypatch.setattr("ai_review.libs.config.prompt.load_resource", lambda **_: dummy_file)
|
|
24
|
+
|
|
25
|
+
config = PromptConfig(system_inline_prompt_files=None)
|
|
26
|
+
result = config.system_inline_prompt_files_or_default
|
|
27
|
+
|
|
28
|
+
assert result == [dummy_file]
|
|
29
|
+
assert config.load_system_inline() == ["GLOBAL"]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_system_inline_prompts_include_true(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
|
|
33
|
+
global_file = tmp_path / "global.md"
|
|
34
|
+
global_file.write_text("GLOBAL")
|
|
35
|
+
custom_file = tmp_path / "custom.md"
|
|
36
|
+
custom_file.write_text("CUSTOM")
|
|
37
|
+
monkeypatch.setattr("ai_review.libs.config.prompt.load_resource", lambda **_: global_file)
|
|
38
|
+
|
|
39
|
+
config = PromptConfig(system_inline_prompt_files=[custom_file], include_inline_system_prompts=True)
|
|
40
|
+
result = config.system_inline_prompt_files_or_default
|
|
41
|
+
|
|
42
|
+
assert global_file in result and custom_file in result
|
|
43
|
+
assert config.load_system_inline() == ["GLOBAL", "CUSTOM"]
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_system_inline_prompts_include_false(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
|
|
47
|
+
global_file = tmp_path / "global.md"
|
|
48
|
+
global_file.write_text("GLOBAL")
|
|
49
|
+
custom_file = tmp_path / "custom.md"
|
|
50
|
+
custom_file.write_text("CUSTOM")
|
|
51
|
+
monkeypatch.setattr("ai_review.libs.config.prompt.load_resource", lambda **_: global_file)
|
|
52
|
+
|
|
53
|
+
config = PromptConfig(system_inline_prompt_files=[custom_file], include_inline_system_prompts=False)
|
|
54
|
+
result = config.system_inline_prompt_files_or_default
|
|
55
|
+
|
|
56
|
+
assert result == [custom_file]
|
|
57
|
+
assert config.load_system_inline() == ["CUSTOM"]
|
|
File without changes
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from ai_review.libs.template.render import render_template
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_replaces_single_variable():
|
|
5
|
+
text = "Hello, <<name>>!"
|
|
6
|
+
values = {"name": "Alice"}
|
|
7
|
+
result = render_template(text, values)
|
|
8
|
+
assert result == "Hello, Alice!"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_replaces_multiple_variables():
|
|
12
|
+
text = "User: <<user>>, Branch: <<branch>>"
|
|
13
|
+
values = {"user": "nikita", "branch": "main"}
|
|
14
|
+
result = render_template(text, values)
|
|
15
|
+
assert result == "User: nikita, Branch: main"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_missing_variable_keeps_placeholder():
|
|
19
|
+
text = "Hello, <<name>>, you are <<role>>"
|
|
20
|
+
values = {"name": "Bob"}
|
|
21
|
+
result = render_template(text, values)
|
|
22
|
+
assert result == "Hello, Bob, you are <<role>>"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_custom_placeholder_format():
|
|
26
|
+
text = "Hello, [[name]]!"
|
|
27
|
+
values = {"name": "Alice"}
|
|
28
|
+
result = render_template(text, values, placeholder="[[{value}]]")
|
|
29
|
+
assert result == "Hello, Alice!"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_placeholder_with_digits_and_underscores():
|
|
33
|
+
text = "Key: <<var_123>>"
|
|
34
|
+
values = {"var_123": "ok"}
|
|
35
|
+
result = render_template(text, values)
|
|
36
|
+
assert result == "Key: ok"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_no_placeholders_in_text():
|
|
40
|
+
text = "Nothing to replace"
|
|
41
|
+
values = {"name": "Alice"}
|
|
42
|
+
result = render_template(text, values)
|
|
43
|
+
assert result == "Nothing to replace"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_partial_overlap_does_not_replace():
|
|
47
|
+
text = "This is <<var>> and <<var_extra>>"
|
|
48
|
+
values = {"var": "A", "var_extra": "B"}
|
|
49
|
+
result = render_template(text, values)
|
|
50
|
+
assert result == "This is A and B"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def test_placeholder_with_dot_and_dash():
|
|
54
|
+
text = "Branch: <<feature-1.2>>"
|
|
55
|
+
values = {"feature-1.2": "ok"}
|
|
56
|
+
result = render_template(text, values)
|
|
57
|
+
assert result == "Branch: ok"
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_multiple_same_placeholders():
|
|
61
|
+
text = "<<name>>, <<name>>, <<name>>!"
|
|
62
|
+
values = {"name": "Alice"}
|
|
63
|
+
result = render_template(text, values)
|
|
64
|
+
assert result == "Alice, Alice, Alice!"
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from ai_review.config import settings
|
|
1
4
|
from ai_review.services.prompt.schema import PromptContextSchema
|
|
2
5
|
|
|
3
6
|
|
|
@@ -6,7 +9,7 @@ def test_apply_format_inserts_variables() -> None:
|
|
|
6
9
|
merge_request_title="My MR",
|
|
7
10
|
merge_request_author_username="nikita"
|
|
8
11
|
)
|
|
9
|
-
template = "Title:
|
|
12
|
+
template = "Title: <<merge_request_title>>, Author: @<<merge_request_author_username>>"
|
|
10
13
|
result = context.apply_format(template)
|
|
11
14
|
assert result == "Title: My MR, Author: @nikita"
|
|
12
15
|
|
|
@@ -19,10 +22,10 @@ def test_apply_format_with_lists() -> None:
|
|
|
19
22
|
changed_files=["a.py", "b.py"],
|
|
20
23
|
)
|
|
21
24
|
template = (
|
|
22
|
-
"Reviewers:
|
|
23
|
-
"Usernames:
|
|
24
|
-
"Labels:
|
|
25
|
-
"Files:
|
|
25
|
+
"Reviewers: <<merge_request_reviewers>>\n"
|
|
26
|
+
"Usernames: <<merge_request_reviewers_usernames>>\n"
|
|
27
|
+
"Labels: <<labels>>\n"
|
|
28
|
+
"Files: <<changed_files>>"
|
|
26
29
|
)
|
|
27
30
|
result = context.apply_format(template)
|
|
28
31
|
assert "Alice, Bob" in result
|
|
@@ -33,6 +36,36 @@ def test_apply_format_with_lists() -> None:
|
|
|
33
36
|
|
|
34
37
|
def test_apply_format_handles_missing_fields() -> None:
|
|
35
38
|
context = PromptContextSchema()
|
|
36
|
-
template = "Title:
|
|
39
|
+
template = "Title: <<merge_request_title>>, Reviewer: <<merge_request_reviewer>>"
|
|
37
40
|
result = context.apply_format(template)
|
|
38
41
|
assert result == "Title: , Reviewer: "
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_apply_format_unknown_placeholder_kept() -> None:
|
|
45
|
+
context = PromptContextSchema()
|
|
46
|
+
template = "Unknown: <<does_not_exist>>"
|
|
47
|
+
result = context.apply_format(template)
|
|
48
|
+
assert result == "Unknown: <<does_not_exist>>"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_apply_format_multiple_occurrences() -> None:
|
|
52
|
+
context = PromptContextSchema(merge_request_title="My MR")
|
|
53
|
+
template = "<<merge_request_title>> again <<merge_request_title>>"
|
|
54
|
+
result = context.apply_format(template)
|
|
55
|
+
assert result == "My MR again My MR"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_apply_format_override_from_settings(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
59
|
+
monkeypatch.setitem(settings.prompt.context, "merge_request_title", "Overridden")
|
|
60
|
+
context = PromptContextSchema(merge_request_title="Local Value")
|
|
61
|
+
template = "Title: <<merge_request_title>>"
|
|
62
|
+
result = context.apply_format(template)
|
|
63
|
+
assert result == "Title: Overridden"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_apply_format_prefers_override_even_if_empty(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
67
|
+
monkeypatch.setitem(settings.prompt.context, "merge_request_title", "")
|
|
68
|
+
context = PromptContextSchema(merge_request_title="Local Value")
|
|
69
|
+
template = "Title: <<merge_request_title>>"
|
|
70
|
+
result = context.apply_format(template)
|
|
71
|
+
assert result == "Title: "
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xai-review
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.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>
|
|
@@ -211,19 +211,38 @@ ai-review:
|
|
|
211
211
|
# Custom context variables
|
|
212
212
|
# ===============================
|
|
213
213
|
# You can inject custom variables into prompts via PROMPT__CONTEXT__*.
|
|
214
|
-
# These will be available
|
|
214
|
+
# These will be available in all templates through placeholders.
|
|
215
|
+
#
|
|
216
|
+
# Placeholder syntax is defined separately in PROMPT__CONTEXT_PLACEHOLDER.
|
|
217
|
+
# Default: <<{value}>>
|
|
215
218
|
#
|
|
216
219
|
# Example usage in prompt templates:
|
|
217
|
-
# Project:
|
|
218
|
-
# Env:
|
|
219
|
-
# Pipeline:
|
|
220
|
+
# Project: <<company_name>>
|
|
221
|
+
# Env: <<environment>>
|
|
222
|
+
# Pipeline: <<ci_pipeline_url>>
|
|
220
223
|
#
|
|
221
224
|
# Values override built-in variables if names collide.
|
|
222
|
-
# To avoid clashes, prefer namespaced keys
|
|
225
|
+
# To avoid clashes, prefer namespaced keys
|
|
226
|
+
# (ci_pipeline_url, org_notify_handle, env_name).
|
|
223
227
|
#
|
|
224
228
|
# PROMPT__CONTEXT__ENVIRONMENT: "staging"
|
|
225
229
|
# PROMPT__CONTEXT__COMPANY_NAME: "ACME Corp"
|
|
226
230
|
# PROMPT__CONTEXT__CI_PIPELINE_URL: "https://gitlab.com/pipelines/123"
|
|
231
|
+
#
|
|
232
|
+
# ===============================
|
|
233
|
+
# Context placeholder
|
|
234
|
+
# ===============================
|
|
235
|
+
# Defines how placeholders are written in prompt templates.
|
|
236
|
+
# Must contain "{value}" which will be replaced by the variable name.
|
|
237
|
+
#
|
|
238
|
+
# Default: <<{value}>>
|
|
239
|
+
#
|
|
240
|
+
# Example:
|
|
241
|
+
# PROMPT__CONTEXT_PLACEHOLDER: "<<{value}>>"
|
|
242
|
+
# Template: "Env: <<environment>>"
|
|
243
|
+
# Result: "Env: staging"
|
|
244
|
+
#
|
|
245
|
+
# PROMPT__CONTEXT_PLACEHOLDER: "<<{value}>>"
|
|
227
246
|
|
|
228
247
|
# ===============================
|
|
229
248
|
# Review options
|
|
@@ -40,7 +40,7 @@ ai_review/libs/config/http.py,sha256=QsIj0yH1IYELOFBQ5AoqPZT0kGIIrQ19cxk1ozPRhLE
|
|
|
40
40
|
ai_review/libs/config/llm.py,sha256=cK-e4NCQxnnixLATCsO8-r5k3zUWz1N0BdPCoqerORM,1824
|
|
41
41
|
ai_review/libs/config/logger.py,sha256=oPmjpjf6EZwW7CgOjT8mOQdGnT98CLwXepiGB_ajZvU,384
|
|
42
42
|
ai_review/libs/config/openai.py,sha256=vOYqhUq0ceEuNdQrQaHq44lVS5M648mB61Zc4YlfJVw,271
|
|
43
|
-
ai_review/libs/config/prompt.py,sha256=
|
|
43
|
+
ai_review/libs/config/prompt.py,sha256=e5jmHsfC6WpnkYZpTLT9TyKQfGtsbqJbxMkJBmLAWf0,4434
|
|
44
44
|
ai_review/libs/config/review.py,sha256=LEZni68iH_0m4URPfN0d3F6yrrK7KSn-BwXf-7w2al8,1058
|
|
45
45
|
ai_review/libs/config/vcs.py,sha256=FduvJJkGObh2LgTSapaMB6FABIvjX7E63yTwZF4p8CU,517
|
|
46
46
|
ai_review/libs/constants/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -58,6 +58,8 @@ ai_review/libs/http/event_hooks/base.py,sha256=cnSOOButTJYKeyb_OnGms1vXRfwfExP81
|
|
|
58
58
|
ai_review/libs/http/event_hooks/logger.py,sha256=CcGk4dmxrOTwsM-QgTHQiJdI8cgLAG-Ay56iygOUCKU,546
|
|
59
59
|
ai_review/libs/http/transports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
60
60
|
ai_review/libs/http/transports/retry.py,sha256=WfY36SEMokjP0-uGv_OKlsaAVpMgePc1aYw3Eq4evTE,1145
|
|
61
|
+
ai_review/libs/template/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
62
|
+
ai_review/libs/template/render.py,sha256=PwLG46fXg8P3gZvmJB93P51G2IBdsEK2I8oDlLGmA-4,414
|
|
61
63
|
ai_review/prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
62
64
|
ai_review/prompts/default_context.md,sha256=W8LvCMQxaX09NhPokwuxYLlA1jPCYor80GgZO8nhKbc,633
|
|
63
65
|
ai_review/prompts/default_inline.md,sha256=UlxozaY5NtdZvA_d3qtAwIQSLP3C5JJh-mJtxGp_u0Q,257
|
|
@@ -94,7 +96,7 @@ ai_review/services/llm/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
|
|
|
94
96
|
ai_review/services/llm/openai/client.py,sha256=WhMXNfH_G1NTlFkdRK5sgYvrCIE5ZQNfPhdYx49IXFk,1143
|
|
95
97
|
ai_review/services/prompt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
96
98
|
ai_review/services/prompt/adapter.py,sha256=xsJwBMmmuD0VIBbA7NCQuE6Zz6WyBoVJE3FuYMLHCxA,1005
|
|
97
|
-
ai_review/services/prompt/schema.py,sha256=
|
|
99
|
+
ai_review/services/prompt/schema.py,sha256=erAecUYzOWyZfixt-pjmPSnvcMDh5DajMd1b7_SPm_o,2052
|
|
98
100
|
ai_review/services/prompt/service.py,sha256=AQG0YnlfXYtuADaZDhWD8NkPHx_zH4TCTOFPzMvZaSs,2078
|
|
99
101
|
ai_review/services/review/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
100
102
|
ai_review/services/review/service.py,sha256=8YhRFqhZAk2pAnkDaytKSCENlOeOti1brAJq3R9tVMY,8394
|
|
@@ -122,21 +124,27 @@ ai_review/tests/suites/clients/claude/test_schema.py,sha256=MUZXvEROgLNpUVHfCsH5
|
|
|
122
124
|
ai_review/tests/suites/clients/gemini/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
123
125
|
ai_review/tests/suites/clients/gemini/test_client.py,sha256=6hxpK7r7iZVbOzAffRNDJnA63-3Zxvqw5ynANPhBhBg,1066
|
|
124
126
|
ai_review/tests/suites/clients/gemini/test_schema.py,sha256=88dU28m7sEWvGx6tqYl7if7weWYuVc8erlkFkKKI3bk,3109
|
|
127
|
+
ai_review/tests/suites/clients/gitlab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
128
|
+
ai_review/tests/suites/clients/gitlab/test_client.py,sha256=vXN7UZLC2yc7P7GZftpVvvUDycqR231ZFnfHZk97VLY,1325
|
|
125
129
|
ai_review/tests/suites/clients/openai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
126
130
|
ai_review/tests/suites/clients/openai/test_client.py,sha256=Ox5ifP1C_gSeDRacBa9DnXhe__Z8-WcbzR2JH_V3xKo,1050
|
|
127
131
|
ai_review/tests/suites/clients/openai/test_schema.py,sha256=x1tamS4GC9pOTpjieKDbK2D73CVV4BkATppytwMevLo,1599
|
|
128
132
|
ai_review/tests/suites/libs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
133
|
+
ai_review/tests/suites/libs/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
134
|
+
ai_review/tests/suites/libs/config/test_prompt.py,sha256=kDMTnykC54tTPfE6cqYRBbV8d5jzAKucXdJfwtqUybM,2242
|
|
129
135
|
ai_review/tests/suites/libs/diff/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
130
136
|
ai_review/tests/suites/libs/diff/test_models.py,sha256=RBFQ97LWhU8TlupxXkJ97ryAvJrSuOHLtT9biUBUMXg,3321
|
|
131
137
|
ai_review/tests/suites/libs/diff/test_parser.py,sha256=rvWEVGIdaLBlDAnSevjRY7I1Zikj12d5GOgMk9QyHQQ,3013
|
|
132
138
|
ai_review/tests/suites/libs/diff/test_tools.py,sha256=XkHJZ-b5veFz5oLKO09P7npaLN8lOzCnGR7e83Zv_mg,1953
|
|
139
|
+
ai_review/tests/suites/libs/template/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
140
|
+
ai_review/tests/suites/libs/template/test_render.py,sha256=n-ss5bd_hwc-RzYmqWmFM6KSlP1zLSnlsW1Yki12Bpw,1890
|
|
133
141
|
ai_review/tests/suites/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
134
142
|
ai_review/tests/suites/services/diff/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
135
143
|
ai_review/tests/suites/services/diff/test_renderers.py,sha256=XFXaOTGAdPOJRb8w-1BOX-eci1C49mKvH4vckybrJSg,5641
|
|
136
144
|
ai_review/tests/suites/services/diff/test_service.py,sha256=iFkGX9Vj2X44JU3eFsoHsg9o9353eKX-QCv_J9KxfzU,3162
|
|
137
145
|
ai_review/tests/suites/services/diff/test_tools.py,sha256=HBQ3eCn-kLeb_k5iTgyr09x0VwLYSegSbxm0Qk9ZrCc,3543
|
|
138
146
|
ai_review/tests/suites/services/prompt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
139
|
-
ai_review/tests/suites/services/prompt/test_schema.py,sha256=
|
|
147
|
+
ai_review/tests/suites/services/prompt/test_schema.py,sha256=XkJk4N9ovgod7G3i6oZwRBjpd71sv0vtVDJhSOfIwGA,2660
|
|
140
148
|
ai_review/tests/suites/services/prompt/test_service.py,sha256=XY7FsAhHUjr56AKVMDgCC7OpXOhj2UirB9pARmLjUuc,5236
|
|
141
149
|
ai_review/tests/suites/services/review/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
142
150
|
ai_review/tests/suites/services/review/inline/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -147,9 +155,9 @@ ai_review/tests/suites/services/review/policy/test_service.py,sha256=kRWT550OjWY
|
|
|
147
155
|
ai_review/tests/suites/services/review/summary/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
148
156
|
ai_review/tests/suites/services/review/summary/test_schema.py,sha256=xSoydvABZldHaVDa0OBFvYrj8wMuZqUDN3MO-XdvxOI,819
|
|
149
157
|
ai_review/tests/suites/services/review/summary/test_service.py,sha256=8UMvi_NL9frm280vD6Q1NCDrdI7K8YbXzoViIus-I2g,541
|
|
150
|
-
xai_review-0.
|
|
151
|
-
xai_review-0.
|
|
152
|
-
xai_review-0.
|
|
153
|
-
xai_review-0.
|
|
154
|
-
xai_review-0.
|
|
155
|
-
xai_review-0.
|
|
158
|
+
xai_review-0.6.0.dist-info/licenses/LICENSE,sha256=p-v8m7Kmz4KKc7PcvsGiGEmCw9AiSXY4_ylOPy_u--Y,11343
|
|
159
|
+
xai_review-0.6.0.dist-info/METADATA,sha256=OQT-Me4_2Dg1CHGNXQCoZBCE2sl1ceHgroCs0axcb3s,9640
|
|
160
|
+
xai_review-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
161
|
+
xai_review-0.6.0.dist-info/entry_points.txt,sha256=JyC5URanMi5io5P_PXQf7H_I1OGIpk5cZQhaPQ0g4Zs,53
|
|
162
|
+
xai_review-0.6.0.dist-info/top_level.txt,sha256=sTsZbfzLoqvRZKdKa-BcxWvjlHdrpbeJ6DrGY0EuR0E,10
|
|
163
|
+
xai_review-0.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|