PyBreeze 1.0.4__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.
- automation_ide/__init__.py +7 -0
- automation_ide/__main__.py +0 -0
- automation_ide/automation_editor_ui/__init__.py +0 -0
- automation_ide/automation_editor_ui/connect_gui/__init__.py +0 -0
- automation_ide/automation_editor_ui/connect_gui/ssh/__init__.py +0 -0
- automation_ide/automation_editor_ui/connect_gui/ssh/ssh_command_widget.py +246 -0
- automation_ide/automation_editor_ui/connect_gui/ssh/ssh_file_viewer_widget.py +501 -0
- automation_ide/automation_editor_ui/connect_gui/ssh/ssh_login_widget.py +67 -0
- automation_ide/automation_editor_ui/connect_gui/ssh/ssh_main_widget.py +49 -0
- automation_ide/automation_editor_ui/connect_gui/url/__init__.py +0 -0
- automation_ide/automation_editor_ui/connect_gui/url/ai_code_review_gui.py +177 -0
- automation_ide/automation_editor_ui/editor_main/__init__.py +0 -0
- automation_ide/automation_editor_ui/editor_main/main_ui.py +104 -0
- automation_ide/automation_editor_ui/extend_ai_gui/__init__.py +0 -0
- automation_ide/automation_editor_ui/extend_ai_gui/ai_gui_global_variable.py +40 -0
- automation_ide/automation_editor_ui/extend_ai_gui/code_review/__init__.py +0 -0
- automation_ide/automation_editor_ui/extend_ai_gui/code_review/code_review_thread.py +81 -0
- automation_ide/automation_editor_ui/extend_ai_gui/code_review/cot_code_review_gui.py +82 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/__init__.py +0 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/__init__.py +0 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/code_smell_detector.py +22 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_code_review.py +17 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_summary_prompt.py +17 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/global_rule.py +59 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/judge.py +91 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/judge_single_review.py +85 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/linter.py +17 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/step_by_step_analysis.py +35 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/total_summary.py +66 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_prompt_editor_widget.py +136 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_editor_widget.py +136 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/__init__.py +0 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_explainer.py +21 -0
- automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_review.py +37 -0
- automation_ide/automation_editor_ui/extend_ai_gui/skills/__init__.py +0 -0
- automation_ide/automation_editor_ui/extend_ai_gui/skills/skills_send_gui.py +98 -0
- automation_ide/automation_editor_ui/extend_multi_language/__init__.py +0 -0
- automation_ide/automation_editor_ui/extend_multi_language/extend_english.py +272 -0
- automation_ide/automation_editor_ui/extend_multi_language/extend_traditional_chinese.py +272 -0
- automation_ide/automation_editor_ui/extend_multi_language/update_language_dict.py +8 -0
- automation_ide/automation_editor_ui/menu/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/automation_menu/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/automation_menu/api_testka_menu/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/automation_menu/api_testka_menu/build_api_testka_menu.py +137 -0
- automation_ide/automation_editor_ui/menu/automation_menu/auto_control_menu/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/automation_menu/auto_control_menu/build_autocontrol_menu.py +169 -0
- automation_ide/automation_editor_ui/menu/automation_menu/automation_file_menu/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/automation_menu/automation_file_menu/build_automation_file_menu.py +122 -0
- automation_ide/automation_editor_ui/menu/automation_menu/load_density_menu/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/automation_menu/load_density_menu/build_load_density_menu.py +137 -0
- automation_ide/automation_editor_ui/menu/automation_menu/mail_thunder_menu/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/automation_menu/mail_thunder_menu/build_mail_thunder_menu.py +88 -0
- automation_ide/automation_editor_ui/menu/automation_menu/test_pioneer_menu/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/automation_menu/test_pioneer_menu/build_test_pioneer_menu.py +62 -0
- automation_ide/automation_editor_ui/menu/automation_menu/web_runner_menu/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/automation_menu/web_runner_menu/build_webrunner_menu.py +119 -0
- automation_ide/automation_editor_ui/menu/build_menubar.py +47 -0
- automation_ide/automation_editor_ui/menu/install_menu/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/install_menu/automation_menu/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/install_menu/automation_menu/build_automation_install_menu.py +82 -0
- automation_ide/automation_editor_ui/menu/install_menu/install_utils.py +21 -0
- automation_ide/automation_editor_ui/menu/install_menu/tools_menu/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/install_menu/tools_menu/build_tool_install_menu.py +29 -0
- automation_ide/automation_editor_ui/menu/menu_utils.py +16 -0
- automation_ide/automation_editor_ui/menu/tools/__init__.py +0 -0
- automation_ide/automation_editor_ui/menu/tools/tools_menu.py +162 -0
- automation_ide/automation_editor_ui/show_code_window/__init__.py +0 -0
- automation_ide/automation_editor_ui/show_code_window/code_window.py +21 -0
- automation_ide/automation_editor_ui/syntax/__init__.py +0 -0
- automation_ide/automation_editor_ui/syntax/syntax_extend.py +40 -0
- automation_ide/automation_editor_ui/syntax/syntax_keyword.py +163 -0
- automation_ide/extend/__init__.py +0 -0
- automation_ide/extend/mail_thunder_extend/__init__.py +0 -0
- automation_ide/extend/mail_thunder_extend/mail_thunder_setting.py +36 -0
- automation_ide/extend/process_executor/__init__.py +0 -0
- automation_ide/extend/process_executor/api_testka/__init__.py +0 -0
- automation_ide/extend/process_executor/api_testka/api_testka_process.py +66 -0
- automation_ide/extend/process_executor/auto_control/__init__.py +0 -0
- automation_ide/extend/process_executor/auto_control/auto_control_process.py +62 -0
- automation_ide/extend/process_executor/file_automation/__init__.py +0 -0
- automation_ide/extend/process_executor/file_automation/file_automation_process.py +66 -0
- automation_ide/extend/process_executor/load_density/__init__.py +0 -0
- automation_ide/extend/process_executor/load_density/load_density_process.py +66 -0
- automation_ide/extend/process_executor/mail_thunder/__init__.py +0 -0
- automation_ide/extend/process_executor/mail_thunder/mail_thunder_process.py +16 -0
- automation_ide/extend/process_executor/process_executor_utils.py +72 -0
- automation_ide/extend/process_executor/python_task_process_manager.py +177 -0
- automation_ide/extend/process_executor/test_pioneer/__init__.py +0 -0
- automation_ide/extend/process_executor/test_pioneer/test_pioneer_process_manager.py +181 -0
- automation_ide/extend/process_executor/web_runner/__init__.py +0 -0
- automation_ide/extend/process_executor/web_runner/web_runner_process.py +66 -0
- automation_ide/utils/__init__.py +0 -0
- automation_ide/utils/exception/__init__.py +0 -0
- automation_ide/utils/exception/exception_tags.py +37 -0
- automation_ide/utils/exception/exceptions.py +50 -0
- automation_ide/utils/file_process/__init__.py +0 -0
- automation_ide/utils/file_process/get_dir_file_list.py +29 -0
- automation_ide/utils/json_format/__init__.py +1 -0
- automation_ide/utils/json_format/json_process.py +28 -0
- automation_ide/utils/logging/__init__.py +0 -0
- automation_ide/utils/logging/logger.py +50 -0
- automation_ide/utils/manager/__init__.py +0 -0
- automation_ide/utils/manager/package_manager/__init__.py +0 -0
- automation_ide/utils/manager/package_manager/package_manager_class.py +18 -0
- pybreeze-1.0.4.dist-info/METADATA +69 -0
- pybreeze-1.0.4.dist-info/RECORD +109 -0
- pybreeze-1.0.4.dist-info/WHEEL +5 -0
- pybreeze-1.0.4.dist-info/licenses/LICENSE +21 -0
- pybreeze-1.0.4.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import requests
|
|
3
|
+
import os
|
|
4
|
+
from PySide6.QtWidgets import (
|
|
5
|
+
QApplication, QWidget, QVBoxLayout, QHBoxLayout,
|
|
6
|
+
QPushButton, QLineEdit, QTextEdit, QComboBox, QLabel, QSizePolicy
|
|
7
|
+
)
|
|
8
|
+
from je_editor import language_wrapper
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AICodeReviewClient(QWidget):
|
|
12
|
+
def __init__(self):
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.word_dict = language_wrapper.language_word_dict
|
|
15
|
+
self.setWindowTitle(self.word_dict.get(
|
|
16
|
+
"ai_code_review_gui_window_title"
|
|
17
|
+
))
|
|
18
|
+
|
|
19
|
+
# 記錄接受/拒絕次數
|
|
20
|
+
self.accept_count = 0
|
|
21
|
+
self.reject_count = 0
|
|
22
|
+
self.stats_file = "response_stats.txt"
|
|
23
|
+
self.url_file = "urls.txt"
|
|
24
|
+
|
|
25
|
+
# 主佈局 (垂直)
|
|
26
|
+
main_layout = QVBoxLayout()
|
|
27
|
+
|
|
28
|
+
# -------------------------------
|
|
29
|
+
# 上方:URL 與 Method
|
|
30
|
+
# -------------------------------
|
|
31
|
+
top_layout = QHBoxLayout()
|
|
32
|
+
|
|
33
|
+
# URL
|
|
34
|
+
url_layout = QHBoxLayout()
|
|
35
|
+
url_layout.addWidget(QLabel(self.word_dict.get("ai_code_review_gui_label_url")))
|
|
36
|
+
self.url_input = QLineEdit()
|
|
37
|
+
url_layout.addWidget(self.url_input)
|
|
38
|
+
top_layout.addLayout(url_layout)
|
|
39
|
+
|
|
40
|
+
# Method
|
|
41
|
+
method_layout = QHBoxLayout()
|
|
42
|
+
method_layout.addWidget(QLabel(self.word_dict.get("ai_code_review_gui_label_method")))
|
|
43
|
+
self.method_box = QComboBox()
|
|
44
|
+
self.method_box.addItems(["GET", "POST", "PUT", "DELETE"])
|
|
45
|
+
method_layout.addWidget(self.method_box)
|
|
46
|
+
top_layout.addLayout(method_layout)
|
|
47
|
+
|
|
48
|
+
main_layout.addLayout(top_layout)
|
|
49
|
+
|
|
50
|
+
# -------------------------------
|
|
51
|
+
# 中間:左右顯示框 (同樣高)
|
|
52
|
+
# -------------------------------
|
|
53
|
+
middle_layout = QHBoxLayout()
|
|
54
|
+
|
|
55
|
+
# 左邊:程式碼輸入
|
|
56
|
+
left_layout = QVBoxLayout()
|
|
57
|
+
left_layout.addWidget(QLabel(
|
|
58
|
+
self.word_dict.get("ai_code_review_gui_label_code_to_send")))
|
|
59
|
+
self.code_input = QTextEdit()
|
|
60
|
+
self.code_input.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
|
61
|
+
left_layout.addWidget(self.code_input)
|
|
62
|
+
|
|
63
|
+
# 右邊:回傳顯示
|
|
64
|
+
right_layout = QVBoxLayout()
|
|
65
|
+
right_layout.addWidget(QLabel(self.word_dict.get("ai_code_review_gui_label_response")))
|
|
66
|
+
self.response_panel = QTextEdit()
|
|
67
|
+
self.response_panel.setReadOnly(True)
|
|
68
|
+
self.response_panel.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
|
69
|
+
right_layout.addWidget(self.response_panel)
|
|
70
|
+
|
|
71
|
+
# 放入中間佈局
|
|
72
|
+
middle_layout.addLayout(left_layout, 1)
|
|
73
|
+
middle_layout.addLayout(right_layout, 1)
|
|
74
|
+
|
|
75
|
+
main_layout.addLayout(middle_layout)
|
|
76
|
+
|
|
77
|
+
# -------------------------------
|
|
78
|
+
# 最下面:發送按鈕
|
|
79
|
+
# -------------------------------
|
|
80
|
+
self.send_button = QPushButton(
|
|
81
|
+
self.word_dict.get("ai_code_review_gui_button_send_request"))
|
|
82
|
+
self.send_button.clicked.connect(self.send_request)
|
|
83
|
+
main_layout.addWidget(self.send_button)
|
|
84
|
+
|
|
85
|
+
# -------------------------------
|
|
86
|
+
# 最下面:接受/不接受按鈕
|
|
87
|
+
# -------------------------------
|
|
88
|
+
bottom_layout = QHBoxLayout()
|
|
89
|
+
self.accept_button = QPushButton(
|
|
90
|
+
self.word_dict.get("ai_code_review_gui_button_accept_response"))
|
|
91
|
+
self.reject_button = QPushButton(
|
|
92
|
+
self.word_dict.get("ai_code_review_gui_button_reject_response"))
|
|
93
|
+
|
|
94
|
+
# 綁定事件
|
|
95
|
+
self.accept_button.clicked.connect(self.accept_response)
|
|
96
|
+
self.reject_button.clicked.connect(self.reject_response)
|
|
97
|
+
|
|
98
|
+
bottom_layout.addWidget(self.accept_button)
|
|
99
|
+
bottom_layout.addWidget(self.reject_button)
|
|
100
|
+
|
|
101
|
+
main_layout.addLayout(bottom_layout)
|
|
102
|
+
|
|
103
|
+
self.setLayout(main_layout)
|
|
104
|
+
|
|
105
|
+
def send_request(self):
|
|
106
|
+
"""Send HTTP request and display result"""
|
|
107
|
+
url = self.url_input.text().strip()
|
|
108
|
+
method = self.method_box.currentText()
|
|
109
|
+
code_content = self.code_input.toPlainText().strip()
|
|
110
|
+
|
|
111
|
+
if not url:
|
|
112
|
+
self.response_panel.setPlainText(
|
|
113
|
+
self.word_dict.get("ai_code_review_gui_message_enter_valid_url"))
|
|
114
|
+
return
|
|
115
|
+
|
|
116
|
+
# 檢查 URL 是否已紀錄
|
|
117
|
+
if os.path.exists(self.url_file):
|
|
118
|
+
with open(self.url_file, "r", encoding="utf-8") as f:
|
|
119
|
+
urls = [line.strip() for line in f.readlines()]
|
|
120
|
+
else:
|
|
121
|
+
urls = []
|
|
122
|
+
|
|
123
|
+
if url in urls:
|
|
124
|
+
self.response_panel.setPlainText(
|
|
125
|
+
self.word_dict.get("ai_code_review_gui_message_url_already_recorded"))
|
|
126
|
+
else:
|
|
127
|
+
with open(self.url_file, "a", encoding="utf-8") as f:
|
|
128
|
+
f.write(url + "\n")
|
|
129
|
+
self.response_panel.setPlainText(
|
|
130
|
+
self.word_dict.get("ai_code_review_gui_message_new_url_recorded"))
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
if method == "GET":
|
|
134
|
+
response = requests.get(url)
|
|
135
|
+
elif method == "POST":
|
|
136
|
+
response = requests.post(url, data={"code": code_content})
|
|
137
|
+
elif method == "PUT":
|
|
138
|
+
response = requests.put(url, data={"code": code_content})
|
|
139
|
+
elif method == "DELETE":
|
|
140
|
+
response = requests.delete(url)
|
|
141
|
+
else:
|
|
142
|
+
self.response_panel.setPlainText(
|
|
143
|
+
self.word_dict.get("ai_code_review_gui_message_unsupported_http_method"))
|
|
144
|
+
return
|
|
145
|
+
|
|
146
|
+
self.response_panel.append(response.text)
|
|
147
|
+
|
|
148
|
+
except Exception as e:
|
|
149
|
+
self.response_panel.setPlainText(f"{self.word_dict.get('ai_code_review_gui_message_error')}: {e}")
|
|
150
|
+
|
|
151
|
+
def accept_response(self):
|
|
152
|
+
"""Accept response code and save"""
|
|
153
|
+
self.accept_count += 1
|
|
154
|
+
self.response_panel.append(f"\n{self.word_dict.get('ai_code_review_gui_status_accepted')}")
|
|
155
|
+
self.save_stats()
|
|
156
|
+
|
|
157
|
+
def reject_response(self):
|
|
158
|
+
"""Reject response code and save"""
|
|
159
|
+
self.reject_count += 1
|
|
160
|
+
self.response_panel.append(f"\n{self.word_dict.get('ai_code_review_gui_status_rejected')}")
|
|
161
|
+
self.save_stats()
|
|
162
|
+
|
|
163
|
+
def save_stats(self):
|
|
164
|
+
"""Save accept/reject counts"""
|
|
165
|
+
try:
|
|
166
|
+
with open(self.stats_file, "w", encoding="utf-8") as f:
|
|
167
|
+
f.write(f"Accepted: {self.accept_count}\n")
|
|
168
|
+
f.write(f"Rejected: {self.reject_count}\n")
|
|
169
|
+
except Exception as e:
|
|
170
|
+
self.response_panel.append(f"\n[{self.word_dict.get('ai_code_review_gui_status_save_failed')}: {e}]")
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
if __name__ == "__main__":
|
|
174
|
+
app = QApplication(sys.argv)
|
|
175
|
+
window = AICodeReviewClient()
|
|
176
|
+
window.showMaximized()
|
|
177
|
+
sys.exit(app.exec())
|
|
File without changes
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from os import environ
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import List, Dict, Type
|
|
6
|
+
|
|
7
|
+
from automation_ide.utils.logging.logger import automation_ide_logger
|
|
8
|
+
|
|
9
|
+
environ["LOCUST_SKIP_MONKEY_PATCH"] = "1"
|
|
10
|
+
|
|
11
|
+
from PySide6.QtCore import QTimer, QCoreApplication
|
|
12
|
+
from PySide6.QtGui import QIcon
|
|
13
|
+
from PySide6.QtWidgets import QApplication, QWidget, QSystemTrayIcon
|
|
14
|
+
from je_editor import EditorMain, language_wrapper
|
|
15
|
+
from qt_material import apply_stylesheet
|
|
16
|
+
|
|
17
|
+
from automation_ide.automation_editor_ui.extend_multi_language.update_language_dict import update_language_dict
|
|
18
|
+
from automation_ide.automation_editor_ui.menu.build_menubar import add_menu_to_menubar
|
|
19
|
+
from automation_ide.automation_editor_ui.syntax.syntax_extend import \
|
|
20
|
+
syntax_extend_package
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
EDITOR_EXTEND_TAB: Dict[str, Type[QWidget]] = {
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class AutomationEditor(EditorMain):
|
|
28
|
+
|
|
29
|
+
def __init__(self, debug_mode: bool = False, show_system_tray_ray: bool = False, extend: bool = False) -> None:
|
|
30
|
+
super().__init__(debug_mode, show_system_tray_ray, extend=True)
|
|
31
|
+
|
|
32
|
+
self.current_run_code_window: List[QWidget] = list()
|
|
33
|
+
# Project compiler if user not choose this will use which to find
|
|
34
|
+
self.python_compiler = None
|
|
35
|
+
# Delete JEditor help
|
|
36
|
+
if self.help_menu:
|
|
37
|
+
self.help_menu.deleteLater()
|
|
38
|
+
|
|
39
|
+
# Update language_dict
|
|
40
|
+
update_language_dict()
|
|
41
|
+
|
|
42
|
+
# Title
|
|
43
|
+
self.setWindowTitle(language_wrapper.language_word_dict.get("automation_editor_application_name"))
|
|
44
|
+
self.setToolTip(language_wrapper.language_word_dict.get("automation_editor_application_name"))
|
|
45
|
+
|
|
46
|
+
# Windows 系統專用:設定應用程式 ID
|
|
47
|
+
# Windows only: set application ID
|
|
48
|
+
if not extend:
|
|
49
|
+
self.id = language_wrapper.language_word_dict.get("automation_editor_application_name")
|
|
50
|
+
if sys.platform in ["win32", "cygwin", "msys"]:
|
|
51
|
+
from ctypes import windll
|
|
52
|
+
windll.shell32.SetCurrentProcessExplicitAppUserModelID(self.id)
|
|
53
|
+
|
|
54
|
+
# Icon
|
|
55
|
+
if not extend:
|
|
56
|
+
self.icon_path = Path(os.getcwd() + "/automation_ide.ico")
|
|
57
|
+
self.icon = QIcon(str(self.icon_path))
|
|
58
|
+
if not self.icon.isNull():
|
|
59
|
+
self.setWindowIcon(self.icon)
|
|
60
|
+
|
|
61
|
+
# Menu
|
|
62
|
+
add_menu_to_menubar(self)
|
|
63
|
+
syntax_extend_package(self)
|
|
64
|
+
|
|
65
|
+
# Tab
|
|
66
|
+
for widget_name, widget in EDITOR_EXTEND_TAB.items():
|
|
67
|
+
self.tab_widget.addTab(widget(), widget_name)
|
|
68
|
+
|
|
69
|
+
if debug_mode:
|
|
70
|
+
close_timer = QTimer(self)
|
|
71
|
+
close_timer.setInterval(10000)
|
|
72
|
+
close_timer.timeout.connect(self.debug_close)
|
|
73
|
+
close_timer.start()
|
|
74
|
+
|
|
75
|
+
def closeEvent(self, event) -> None:
|
|
76
|
+
for widget in self.current_run_code_window:
|
|
77
|
+
widget.close()
|
|
78
|
+
super().closeEvent(event)
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
def debug_close(cls) -> None:
|
|
82
|
+
"""
|
|
83
|
+
Use to run CI test.
|
|
84
|
+
:return: None
|
|
85
|
+
"""
|
|
86
|
+
sys.exit(0)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def start_editor(debug_mode: bool = False, **kwargs) -> None:
|
|
90
|
+
"""
|
|
91
|
+
Start editor instance
|
|
92
|
+
:return: None
|
|
93
|
+
"""
|
|
94
|
+
new_ide = QCoreApplication.instance()
|
|
95
|
+
if new_ide is None:
|
|
96
|
+
new_ide = QApplication(sys.argv)
|
|
97
|
+
window = AutomationEditor(debug_mode=debug_mode, **kwargs)
|
|
98
|
+
apply_stylesheet(new_ide, theme="dark_amber.xml")
|
|
99
|
+
window.showMaximized()
|
|
100
|
+
try:
|
|
101
|
+
window.startup_setting()
|
|
102
|
+
except Exception as error:
|
|
103
|
+
print(repr(error))
|
|
104
|
+
sys.exit(new_ide.exec())
|
|
File without changes
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.code_smell_detector import \
|
|
2
|
+
CODE_SMELL_DETECTOR_TEMPLATE
|
|
3
|
+
from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.first_code_review import \
|
|
4
|
+
FIRST_CODE_REVIEW_TEMPLATE
|
|
5
|
+
from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.first_summary_prompt import \
|
|
6
|
+
FIRST_SUMMARY_TEMPLATE
|
|
7
|
+
from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.linter import \
|
|
8
|
+
LINTER_TEMPLATE
|
|
9
|
+
from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.total_summary import \
|
|
10
|
+
TOTAL_SUMMARY_TEMPLATE
|
|
11
|
+
from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.skills_prompt_templates.code_explainer import \
|
|
12
|
+
CODE_EXPLAINER_TEMPLATE
|
|
13
|
+
from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.skills_prompt_templates.code_review import \
|
|
14
|
+
CODE_REVIEW_SKILL_TEMPLATE
|
|
15
|
+
|
|
16
|
+
COT_TEMPLATE_FILES = [
|
|
17
|
+
"first_summary_prompt.md",
|
|
18
|
+
"first_code_review.md",
|
|
19
|
+
"linter.md",
|
|
20
|
+
"code_smell_detector.md",
|
|
21
|
+
"total_summary.md",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
COT_TEMPLATE_RELATION = {
|
|
25
|
+
"first_summary_prompt.md": FIRST_SUMMARY_TEMPLATE,
|
|
26
|
+
"first_code_review.md": FIRST_CODE_REVIEW_TEMPLATE,
|
|
27
|
+
"linter.md": LINTER_TEMPLATE,
|
|
28
|
+
"code_smell_detector.md": CODE_SMELL_DETECTOR_TEMPLATE,
|
|
29
|
+
"total_summary.md": TOTAL_SUMMARY_TEMPLATE,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
SKILLS_TEMPLATE_FILES = [
|
|
33
|
+
"code_review_skill.md",
|
|
34
|
+
"code_explainer_skill.md",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
SKILLS_TEMPLATE_RELATION = {
|
|
38
|
+
"code_review_skill.md": CODE_REVIEW_SKILL_TEMPLATE,
|
|
39
|
+
"code_explainer_skill.md": CODE_EXPLAINER_TEMPLATE
|
|
40
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Worker Thread 負責傳送資料
|
|
2
|
+
import requests
|
|
3
|
+
from PySide6.QtCore import QThread, Signal
|
|
4
|
+
from je_editor import language_wrapper
|
|
5
|
+
|
|
6
|
+
from automation_ide.automation_editor_ui.extend_ai_gui.ai_gui_global_variable import COT_TEMPLATE_RELATION
|
|
7
|
+
from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.global_rule import \
|
|
8
|
+
build_global_rule_template
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SenderThread(QThread):
|
|
12
|
+
update_response = Signal(str, str) # (filename, response)
|
|
13
|
+
|
|
14
|
+
def __init__(self, files: list, code: str, url: str):
|
|
15
|
+
super().__init__()
|
|
16
|
+
self.files = files
|
|
17
|
+
self.code = code
|
|
18
|
+
self.url = url
|
|
19
|
+
|
|
20
|
+
def run(self):
|
|
21
|
+
code = self.code
|
|
22
|
+
first_code_review_result = None
|
|
23
|
+
first_summary_result = None
|
|
24
|
+
linter_result = None
|
|
25
|
+
code_smell_result = None
|
|
26
|
+
for file in self.files:
|
|
27
|
+
match file:
|
|
28
|
+
case "first_summary_prompt.md":
|
|
29
|
+
first_summary_prompt = COT_TEMPLATE_RELATION.get("first_summary_prompt.md")
|
|
30
|
+
prompt = build_global_rule_template(
|
|
31
|
+
prompt=first_summary_prompt.format(code_diff=code)
|
|
32
|
+
)
|
|
33
|
+
case "first_code_review.md":
|
|
34
|
+
first_code_review_prompt = COT_TEMPLATE_RELATION.get("first_code_review.md")
|
|
35
|
+
prompt = build_global_rule_template(
|
|
36
|
+
prompt=first_code_review_prompt.format(code_diff=code)
|
|
37
|
+
)
|
|
38
|
+
case "linter.md":
|
|
39
|
+
linter_prompt = COT_TEMPLATE_RELATION.get("linter.md")
|
|
40
|
+
prompt = build_global_rule_template(
|
|
41
|
+
prompt=linter_prompt.format(code_diff=code)
|
|
42
|
+
)
|
|
43
|
+
case "code_smell_detector.md":
|
|
44
|
+
code_smell_detector_prompt = COT_TEMPLATE_RELATION.get("code_smell_detector.md")
|
|
45
|
+
prompt = build_global_rule_template(
|
|
46
|
+
prompt=code_smell_detector_prompt.format(code_diff=code)
|
|
47
|
+
)
|
|
48
|
+
case "total_summary.md":
|
|
49
|
+
total_summary_prompt = COT_TEMPLATE_RELATION.get("total_summary.md")
|
|
50
|
+
prompt = build_global_rule_template(
|
|
51
|
+
prompt=total_summary_prompt.format(
|
|
52
|
+
first_code_review=first_code_review_result,
|
|
53
|
+
first_summary=first_summary_result,
|
|
54
|
+
linter_result=linter_result,
|
|
55
|
+
code_smell_result=code_smell_result,
|
|
56
|
+
code_diff=code,
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
case _:
|
|
60
|
+
continue
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
# 傳送到指定 URL
|
|
64
|
+
resp = requests.post(self.url, json={"prompt": prompt})
|
|
65
|
+
reply_text = resp.text
|
|
66
|
+
match file:
|
|
67
|
+
case "first_summary_prompt.md":
|
|
68
|
+
first_summary_result = reply_text
|
|
69
|
+
case "first_code_review.md":
|
|
70
|
+
first_code_review_result = reply_text
|
|
71
|
+
case "linter.md":
|
|
72
|
+
linter_result = reply_text
|
|
73
|
+
case "code_smell_detector.md":
|
|
74
|
+
code_smell_result = reply_text
|
|
75
|
+
case _:
|
|
76
|
+
continue
|
|
77
|
+
except Exception as e:
|
|
78
|
+
reply_text = f"{language_wrapper.language_word_dict.get("cot_gui_error_sending")} {file} {e}"
|
|
79
|
+
|
|
80
|
+
# 發送訊號更新 UI
|
|
81
|
+
self.update_response.emit(file, reply_text)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from PySide6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QTextEdit, QComboBox, QPushButton, \
|
|
2
|
+
QMessageBox
|
|
3
|
+
from je_editor import language_wrapper
|
|
4
|
+
|
|
5
|
+
from automation_ide.automation_editor_ui.extend_ai_gui.ai_gui_global_variable import COT_TEMPLATE_FILES
|
|
6
|
+
from automation_ide.automation_editor_ui.extend_ai_gui.code_review.code_review_thread import SenderThread
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CoTCodeReviewGUI(QWidget):
|
|
10
|
+
def __init__(self):
|
|
11
|
+
super().__init__()
|
|
12
|
+
self.setWindowTitle(language_wrapper.language_word_dict.get("cot_gui_window_title"))
|
|
13
|
+
|
|
14
|
+
# 檔案清單
|
|
15
|
+
self.files = COT_TEMPLATE_FILES
|
|
16
|
+
|
|
17
|
+
# UI 元件
|
|
18
|
+
layout = QVBoxLayout()
|
|
19
|
+
|
|
20
|
+
# URL 輸入框
|
|
21
|
+
url_layout = QHBoxLayout()
|
|
22
|
+
url_layout.addWidget(QLabel(language_wrapper.language_word_dict.get("cot_gui_label_api_url")))
|
|
23
|
+
self.url_input = QLineEdit()
|
|
24
|
+
self.url_input.setPlaceholderText(language_wrapper.language_word_dict.get("cot_gui_placeholder_api_url"))
|
|
25
|
+
url_layout.addWidget(self.url_input)
|
|
26
|
+
layout.addLayout(url_layout)
|
|
27
|
+
|
|
28
|
+
# 傳送資料區域
|
|
29
|
+
self.code_paste_area = QTextEdit()
|
|
30
|
+
self.code_paste_area.setPlaceholderText(
|
|
31
|
+
language_wrapper.language_word_dict.get("cot_gui_placeholder_code_paste_area"))
|
|
32
|
+
layout.addWidget(QLabel(language_wrapper.language_word_dict.get("cot_gui_label_prompt_area")))
|
|
33
|
+
layout.addWidget(self.code_paste_area)
|
|
34
|
+
|
|
35
|
+
# 回傳區域
|
|
36
|
+
self.response_selector = QComboBox() # 改用 ComboBox
|
|
37
|
+
self.response_view = QTextEdit()
|
|
38
|
+
self.response_view.setReadOnly(True) # 可複製但不可編輯
|
|
39
|
+
|
|
40
|
+
hbox_layout = QHBoxLayout()
|
|
41
|
+
hbox_layout.addWidget(self.response_selector, 2)
|
|
42
|
+
hbox_layout.addWidget(self.response_view, 5)
|
|
43
|
+
|
|
44
|
+
layout.addWidget(QLabel(language_wrapper.language_word_dict.get("cot_gui_label_response_area")))
|
|
45
|
+
layout.addLayout(hbox_layout)
|
|
46
|
+
|
|
47
|
+
# 傳送按鈕
|
|
48
|
+
self.send_button = QPushButton(language_wrapper.language_word_dict.get("cot_gui_button_send"))
|
|
49
|
+
layout.addWidget(self.send_button)
|
|
50
|
+
|
|
51
|
+
self.setLayout(layout)
|
|
52
|
+
|
|
53
|
+
# 綁定事件
|
|
54
|
+
self.response_selector.currentTextChanged.connect(self.show_response)
|
|
55
|
+
self.send_button.clicked.connect(self.start_sending)
|
|
56
|
+
|
|
57
|
+
# 儲存回覆
|
|
58
|
+
self.responses = {}
|
|
59
|
+
|
|
60
|
+
def show_response(self, filename):
|
|
61
|
+
if filename in self.responses:
|
|
62
|
+
self.response_view.setPlainText(self.responses[filename])
|
|
63
|
+
|
|
64
|
+
def start_sending(self):
|
|
65
|
+
# 取得 URL
|
|
66
|
+
url = self.url_input.text().strip()
|
|
67
|
+
if not url:
|
|
68
|
+
message_box = QMessageBox()
|
|
69
|
+
message_box.warning(self, "Warning", language_wrapper.language_word_dict.get("cot_gui_error_no_url"))
|
|
70
|
+
message_box.exec_()
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
# 啟動傳送 Thread
|
|
74
|
+
self.thread = SenderThread(files=self.files, code=self.code_paste_area.toPlainText(), url=url)
|
|
75
|
+
self.thread.update_response.connect(self.handle_response)
|
|
76
|
+
self.thread.start()
|
|
77
|
+
|
|
78
|
+
def handle_response(self, filename, response):
|
|
79
|
+
self.responses[filename] = response
|
|
80
|
+
self.response_selector.addItem(filename) # 加入 ComboBox
|
|
81
|
+
# 自動顯示最新回覆
|
|
82
|
+
self.response_selector.setCurrentText(filename)
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
CODE_SMELL_DETECTOR_TEMPLATE = """
|
|
2
|
+
You are a senior software engineer specializing in code quality reviews.
|
|
3
|
+
Carefully analyze the following code and identify all possible **code smells**.
|
|
4
|
+
Provide a structured and detailed output.
|
|
5
|
+
|
|
6
|
+
### Output Requirements:
|
|
7
|
+
1. **Code Smell Type**: Specify the exact issue (e.g., long function, magic numbers, duplicate code, unclear naming, tight coupling, violation of single responsibility principle, etc.).
|
|
8
|
+
2. **Problem Location**: Point out the relevant code block or example.
|
|
9
|
+
3. **Detailed Explanation**: Explain why this is considered a code smell and what problems it may cause in terms of readability, maintainability, or scalability.
|
|
10
|
+
4. **Improvement Suggestions**: Provide specific refactoring or optimization recommendations that follow software engineering best practices.
|
|
11
|
+
5. **Priority Level**: Rank the severity as High, Medium, or Low to help developers decide the order of fixes.
|
|
12
|
+
|
|
13
|
+
### Output Format:
|
|
14
|
+
- Code Smell Type:
|
|
15
|
+
- Problem Location:
|
|
16
|
+
- Detailed Explanation:
|
|
17
|
+
- Improvement Suggestions:
|
|
18
|
+
- Priority Level:
|
|
19
|
+
|
|
20
|
+
### Code:
|
|
21
|
+
{code_diff}
|
|
22
|
+
"""
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
FIRST_CODE_REVIEW_TEMPLATE = """
|
|
2
|
+
# Code Review Template
|
|
3
|
+
|
|
4
|
+
## Review Rules
|
|
5
|
+
Perform a first-step code review focusing on:
|
|
6
|
+
1. Code readability (indentation, formatting, comments).
|
|
7
|
+
2. Clarity and descriptiveness of variable, function, and class names; avoid vague or cryptic naming.
|
|
8
|
+
3. Adherence to basic software engineering standards (modularity, maintainability, avoidance of duplicate code).
|
|
9
|
+
4. Identification of obvious logical errors or potential bugs.
|
|
10
|
+
5. Provide concise improvement suggestions with short explanations.
|
|
11
|
+
6. Focus only on the most obvious issues; avoid deep analysis at this stage.
|
|
12
|
+
|
|
13
|
+
Respond in a structured bullet-point format, keeping feedback concise and professional.
|
|
14
|
+
|
|
15
|
+
## Code diff
|
|
16
|
+
{code_diff}
|
|
17
|
+
"""
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
FIRST_SUMMARY_TEMPLATE = """
|
|
2
|
+
# PR Summary Template
|
|
3
|
+
|
|
4
|
+
## Summary Rules
|
|
5
|
+
Generate a first-step Pull Request summary focusing on:
|
|
6
|
+
1. Key changes: Briefly describe the core modifications or new features.
|
|
7
|
+
2. Impact scope: Identify affected modules, files, or functionalities.
|
|
8
|
+
3. Purpose of changes: Explain why these modifications are needed (e.g., bug fix, performance optimization, feature addition).
|
|
9
|
+
4. Risks and considerations: Highlight potential impacts on existing functionality or areas requiring extra testing.
|
|
10
|
+
5. Items to confirm: List specific points that reviewers should pay attention to or validate.
|
|
11
|
+
6. Avoid excessive technical detail; keep the summary high-level for quick team understanding.
|
|
12
|
+
|
|
13
|
+
Write in structured bullet points; keep concise and professional.
|
|
14
|
+
|
|
15
|
+
## Code diff to review
|
|
16
|
+
{code_diff}
|
|
17
|
+
"""
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
GLOBAL_RULE_TEMPLATE = """
|
|
2
|
+
Please conduct a code review according to the following global rules:
|
|
3
|
+
|
|
4
|
+
1. Readability & Consistency
|
|
5
|
+
- Check indentation, formatting, and comments for clarity.
|
|
6
|
+
- Ensure code style follows team conventions (naming rules, formatting tools).
|
|
7
|
+
|
|
8
|
+
2. Naming Conventions
|
|
9
|
+
- Variable, function, and class names must be descriptive and meaningful.
|
|
10
|
+
- Maintain semantic clarity and consistency across the codebase.
|
|
11
|
+
|
|
12
|
+
3. Software Engineering Standards
|
|
13
|
+
- Code should be modular, maintainable, and testable.
|
|
14
|
+
- Avoid duplicate code; encourage refactoring and abstraction.
|
|
15
|
+
|
|
16
|
+
4. Logic & Correctness
|
|
17
|
+
- Verify correctness of program logic and identify potential bugs.
|
|
18
|
+
- Check boundary conditions and exception handling.
|
|
19
|
+
|
|
20
|
+
5. Performance & Security
|
|
21
|
+
- Assess for unnecessary performance bottlenecks.
|
|
22
|
+
- Review for security risks (e.g., input validation, resource management).
|
|
23
|
+
|
|
24
|
+
6. Documentation & Testing
|
|
25
|
+
- Ensure necessary comments and documentation are present.
|
|
26
|
+
- Verify sufficient unit and integration tests are included.
|
|
27
|
+
|
|
28
|
+
7. Scoring & Feedback Style
|
|
29
|
+
- Balance conciseness with comprehensiveness.
|
|
30
|
+
- Do not penalize completeness for being less concise.
|
|
31
|
+
|
|
32
|
+
{rag_rules_section}
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
# Prompt Content
|
|
36
|
+
{prompt}
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def build_global_rule_template(rag_rules=None, prompt=""):
|
|
40
|
+
if not rag_rules:
|
|
41
|
+
rag_rules_section = "" # 忽略 RAG Rules 區塊
|
|
42
|
+
else:
|
|
43
|
+
if isinstance(rag_rules, list):
|
|
44
|
+
rag_rules_text = "".join(f" - {rule}" for rule in rag_rules)
|
|
45
|
+
else:
|
|
46
|
+
rag_rules_text = f" - {rag_rules}"
|
|
47
|
+
|
|
48
|
+
rag_rules_section = f"""
|
|
49
|
+
8. RAG Rules (Retrieval-Augmented Guidance)
|
|
50
|
+
- Apply RAG-provided rules when available.
|
|
51
|
+
- If a rule conflicts or duplicates existing global rules, prioritize the RAG rule.
|
|
52
|
+
- Ensure integration of RAG rules maintains consistency with overall review standards.
|
|
53
|
+
{rag_rules_text}
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
return GLOBAL_RULE_TEMPLATE.format(
|
|
57
|
+
rag_rules_section=rag_rules_section,
|
|
58
|
+
prompt=prompt
|
|
59
|
+
)
|