Skip to content

Commit 4a41cd6

Browse files
committed
Merge branch 'main_upstream'
# Conflicts: # api.py # biz/event/event_manager.py # biz/utils/code_reviewer.py # locales/zh_CN/prompt_templates.yml # requirements.txt
2 parents d1478dc + c52ec96 commit 4a41cd6

File tree

19 files changed

+646
-185
lines changed

19 files changed

+646
-185
lines changed

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,19 @@ streamlit run ui.py --server.port=5002 --server.address=0.0.0.0
158158
FEISHU_WEBHOOK_URL=https://open.feishu.cn/open-apis/bot/v2/hook/xxx #替换为你的Webhook URL
159159
```
160160

161-
## 常见问题
161+
## 其它
162+
163+
**1.如何review代码结构?**
164+
165+
可通过命令工具对代码结构进行检查,命令如下:
166+
167+
```aiignore
168+
python -m biz.cmd.review
169+
```
170+
171+
然后按照提示进行操作即可。
172+
173+
**2.其它问题**
162174

163175
参见 [常见问题](doc/faq.md)
164176

api.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from datetime import datetime
66
from urllib.parse import urlparse
77

8+
from biz.utils.token_util import count_tokens, truncate_text_by_tokens
89
from apscheduler.schedulers.background import BackgroundScheduler
910
from apscheduler.triggers.cron import CronTrigger
1011
from dotenv import load_dotenv
@@ -13,7 +14,7 @@
1314
from biz.gitlab.webhook_handler import slugify_url
1415
from biz.queue.worker import handle_merge_request_event, handle_push_event
1516
from biz.service.review_service import ReviewService
16-
from biz.utils.im import im_notifier
17+
from biz.utils.im import notifier
1718
from biz.utils.log import logger
1819
from biz.utils.queue import handle_queue
1920
from biz.utils.reporter import Reporter
@@ -59,7 +60,7 @@ def daily_report():
5960
# 生成日报内容
6061
report_txt = Reporter().generate_report(json.dumps(commits))
6162
# 发送钉钉通知
62-
im_notifier.send_notification(content=report_txt, msg_type="markdown", title=_("代码提交日报"))
63+
notifier.send_notification(content=report_txt, msg_type="markdown", title=_("代码提交日报"))
6364

6465
# 返回生成的日报内容
6566
return json.dumps(report_txt, ensure_ascii=False, indent=4)

biz/cmd/__init__.py

Whitespace-only changes.

biz/cmd/review.py

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import os
2+
from pathlib import Path
3+
4+
from dotenv import load_dotenv
5+
from pathspec import PathSpec, GitIgnorePattern
6+
7+
from biz.utils.code_reviewer import CodeBaseReviewer
8+
from biz.utils.dir_util import get_directory_tree
9+
from biz.utils.i18n import get_translator
10+
from biz.utils.log import logger
11+
from biz.utils.token_util import count_tokens, truncate_text_by_tokens
12+
13+
_ = get_translator()
14+
15+
SUPPORTED_LANGUAGES = ["python", "java", "php", "vue"]
16+
17+
18+
def validate_language_choice(choice):
19+
"""
20+
验证用户输入的数字是否有效。
21+
:param choice: 用户输入的数字
22+
:return: 如果有效返回 True,否则返回 False
23+
"""
24+
return choice.isdigit() and 1 <= int(choice) <= len(SUPPORTED_LANGUAGES)
25+
26+
27+
def validate_directory(directory):
28+
"""
29+
验证用户输入的目录是否存在。
30+
:param directory: 用户输入的目录路径
31+
:return: 如果目录存在返回 True,否则返回 False
32+
"""
33+
return Path(directory).is_dir()
34+
35+
36+
def get_user_input(prompt: str, default=None, input_type=str):
37+
"""
38+
获取用户输入,支持默认值和类型转换。
39+
40+
Args:
41+
prompt (str): 提示信息。
42+
default: 默认值。
43+
input_type: 输入值的类型(如 int, str, bool 等)。
44+
45+
Returns:
46+
用户输入的值或默认值。
47+
"""
48+
user_input = input(f"{prompt} (默认: {default}): ").strip()
49+
if not user_input:
50+
return default
51+
try:
52+
return input_type(user_input)
53+
except ValueError:
54+
print(_("输入无效,请输入 {} 类型的值。").format(input_type.__name__))
55+
return get_user_input(prompt, default, input_type)
56+
57+
58+
def parse_arguments():
59+
"""
60+
使用交互方式获取用户输入,并返回语言和目录。
61+
:return: 语言和目录的元组 (language, directory)
62+
"""
63+
# 显示语言选项
64+
print(_("请选择开发语言:"))
65+
for index, language in enumerate(SUPPORTED_LANGUAGES, start=1):
66+
print(f"{index}. {language}")
67+
68+
# 获取开发语言
69+
while True:
70+
choice = input(_("请输入数字 (1-{}): ").format(len(SUPPORTED_LANGUAGES)).strip())
71+
if validate_language_choice(choice):
72+
language = SUPPORTED_LANGUAGES[int(choice) - 1] # 获取对应的语言
73+
break
74+
print(_("❌ 无效的选择,请输入 1 到 {} 之间的数字").format(len(SUPPORTED_LANGUAGES)))
75+
76+
# 获取项目目录
77+
while True:
78+
directory = input(_("请输入代码项目的根目录路径: ")).strip()
79+
if validate_directory(directory):
80+
break
81+
print(_("❌ 目录不存在,请输入有效路径"))
82+
83+
max_depth = get_user_input(_("请输入目录树的最大深度"), default=3, input_type=int)
84+
only_dirs = get_user_input(_("是否仅获取目录?(y/n)"), default="y").lower() in ["y", "yes"]
85+
86+
return language, directory, max_depth, only_dirs
87+
88+
89+
def load_gitignore_patterns(directory):
90+
"""加载 .gitignore 规则"""
91+
gitignore_path = os.path.join(directory, ".gitignore")
92+
93+
if not os.path.exists(gitignore_path):
94+
return None # 没有 .gitignore 文件,则不做忽略处理
95+
96+
with open(gitignore_path, "r", encoding="utf-8") as f:
97+
patterns = f.readlines()
98+
99+
return PathSpec.from_lines(GitIgnorePattern, patterns)
100+
101+
102+
def review_code(text: str) -> str:
103+
# 如果超长,取前REVIEW_MAX_TOKENS个token
104+
review_max_tokens = int(os.getenv('REVIEW_MAX_TOKENS', 10000))
105+
# 如果changes为空,打印日志
106+
if not text:
107+
logger.info(_('代码为空, diffs_text = {}').format(str(text)))
108+
return _('代码为空')
109+
110+
# 计算tokens数量,如果超过REVIEW_MAX_TOKENS,截断changes_text
111+
tokens_count = count_tokens(text)
112+
if tokens_count > review_max_tokens:
113+
text = truncate_text_by_tokens(text, review_max_tokens)
114+
115+
review_result = CodeBaseReviewer().review_code(text).strip()
116+
if review_result.startswith("```markdown") and review_result.endswith("```"):
117+
return review_result[11:-3].strip()
118+
return review_result
119+
120+
121+
def confirm_action(prompt: str) -> bool:
122+
while True:
123+
user_input = input(prompt).strip().lower()
124+
if user_input in ["y", "yes"]:
125+
return True
126+
elif user_input in ["n", "no"]:
127+
return False
128+
else:
129+
print(_("请输入 'y' 或 'n' 确认。"))
130+
131+
132+
if __name__ == "__main__":
133+
load_dotenv("conf/.env")
134+
135+
language, directory, max_depth, only_dirs = parse_arguments()
136+
ignore_spec = load_gitignore_patterns(directory)
137+
directory_structure = get_directory_tree(directory, ignore_spec, max_depth=max_depth, only_dirs=only_dirs)
138+
print(_("目录结构:\n"), directory_structure)
139+
140+
# 用户确认
141+
if confirm_action(_("是否确认发送 Review 请求?(y/n): ")):
142+
# 初始化 CodeBaseReviewer
143+
reviewer = CodeBaseReviewer()
144+
145+
# 执行 CodeReview
146+
result = reviewer.review_code(language, directory_structure)
147+
print(_("Review 结果:\n"), result)
148+
else:
149+
print(_("用户取消操作,退出程序。"))

biz/event/event_manager.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from biz.entity.review_entity import MergeRequestReviewEntity, PushReviewEntity
44
from biz.service.review_service import ReviewService
5-
from biz.utils.im import im_notifier
5+
from biz.utils.im import notifier
66

77
from biz.utils.i18n import get_translator
88
_ = get_translator()
@@ -43,7 +43,7 @@ def on_merge_request_reviewed(mr_review_entity: MergeRequestReviewEntity):
4343
url=mr_review_entity.url,
4444
review_result=mr_review_entity.review_result
4545
)
46-
im_notifier.send_notification(content=im_msg, msg_type='markdown', title=_('Merge Request Review'),
46+
notifier.send_notification(content=im_msg, msg_type='markdown', title=_('Merge Request Review'),
4747
project_name=mr_review_entity.project_name,
4848
gitlab_url_slug=mr_review_entity.gitlab_url_slug)
4949

@@ -75,7 +75,7 @@ def on_push_reviewed(entity: PushReviewEntity):
7575

7676
if entity.review_result:
7777
im_msg += _("#### AI Review 结果: \n {review_result}\n\n").format(review_result=entity.review_result)
78-
im_notifier.send_notification(content=im_msg, msg_type='markdown',
78+
notifier.send_notification(content=im_msg, msg_type='markdown',
7979
title=_("{project_name} Push Event").format(project_name=entity.project_name),
8080
project_name=entity.project_name,
8181
gitlab_url_slug=entity.gitlab_url_slug)

biz/queue/worker.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from biz.event.event_manager import event_manager
99
from biz.gitlab.webhook_handler import filter_changes, MergeRequestHandler, PushHandler
1010
from biz.utils.code_reviewer import CodeReviewer
11-
from biz.utils.im import im_notifier
11+
from biz.utils.im import notifier
1212
from biz.utils.log import logger
1313

1414
load_dotenv()
@@ -58,7 +58,7 @@ def handle_push_event(webhook_data: dict, gitlab_token: str, gitlab_url: str, gi
5858

5959
except Exception as e:
6060
error_message = _('服务出现未知错误: {}').format(f'{str(e)}\n{traceback.format_exc()}')
61-
im_notifier.send_notification(content=error_message)
61+
notifier.send_notification(content=error_message)
6262
logger.error(_('出现未知错误: {}').format(error_message))
6363

6464

@@ -121,5 +121,5 @@ def handle_merge_request_event(webhook_data: dict, gitlab_token: str, gitlab_url
121121

122122
except Exception as e:
123123
error_message = _('AI Code Review 服务出现未知错误: {}').format(f'{str(e)}\n{traceback.format_exc()}')
124-
im_notifier.send_notification(content=error_message)
124+
notifier.send_notification(content=error_message)
125125
logger.error(_('出现未知错误: {}').format(error_message))

0 commit comments

Comments
 (0)