diff --git a/automation_ide/automation_editor_ui/editor_main/main_ui.py b/automation_ide/automation_editor_ui/editor_main/main_ui.py index 398d183..6dcf610 100644 --- a/automation_ide/automation_editor_ui/editor_main/main_ui.py +++ b/automation_ide/automation_editor_ui/editor_main/main_ui.py @@ -4,6 +4,8 @@ from pathlib import Path from typing import List, Dict, Type +from automation_ide.utils.logging.logger import automation_ide_logger + environ["LOCUST_SKIP_MONKEY_PATCH"] = "1" from PySide6.QtCore import QTimer, QCoreApplication @@ -24,33 +26,46 @@ class AutomationEditor(EditorMain): - def __init__(self, debug_mode: bool = False, show_system_tray_ray: bool = False): - super().__init__(debug_mode, show_system_tray_ray) + def __init__(self, debug_mode: bool = False, show_system_tray_ray: bool = False, extend: bool = False) -> None: + super().__init__(debug_mode, show_system_tray_ray, extend=True) + self.current_run_code_window: List[QWidget] = list() # Project compiler if user not choose this will use which to find self.python_compiler = None # Delete JEditor help if self.help_menu: self.help_menu.deleteLater() - # System tray change - if self.show_system_tray_ray: - self.system_tray.main_window = self - self.system_tray.setToolTip(language_wrapper.language_word_dict.get("automation_editor_application_name")) + # Update language_dict update_language_dict() + + # Title + self.setWindowTitle(language_wrapper.language_word_dict.get("automation_editor_application_name")) + self.setToolTip(language_wrapper.language_word_dict.get("automation_editor_application_name")) + + # Windows 系統專用:設定應用程式 ID + # Windows only: set application ID + if not extend: + self.id = language_wrapper.language_word_dict.get("automation_editor_application_name") + if sys.platform in ["win32", "cygwin", "msys"]: + from ctypes import windll + windll.shell32.SetCurrentProcessExplicitAppUserModelID(self.id) + + # Icon + if not extend: + self.icon_path = Path(os.getcwd() + "/automation_ide.ico") + self.icon = QIcon(str(self.icon_path)) + if not self.icon.isNull(): + self.setWindowIcon(self.icon) + # Menu add_menu_to_menubar(self) syntax_extend_package(self) + # Tab for widget_name, widget in EDITOR_EXTEND_TAB.items(): self.tab_widget.addTab(widget(), widget_name) - # Icon - self.icon_path = Path(os.getcwd() + "/je_driver_icon.ico") - self.icon = QIcon(str(self.icon_path)) - self.system_tray = QSystemTrayIcon() - self.system_tray.setIcon(self.icon) - # Title - self.setWindowTitle(language_wrapper.language_word_dict.get("automation_editor_application_name")) + if debug_mode: close_timer = QTimer(self) close_timer.setInterval(10000) @@ -76,14 +91,14 @@ def start_editor(debug_mode: bool = False, **kwargs) -> None: Start editor instance :return: None """ - new_editor = QCoreApplication.instance() - if new_editor is None: - new_editor = QApplication(sys.argv) + new_ide = QCoreApplication.instance() + if new_ide is None: + new_ide = QApplication(sys.argv) window = AutomationEditor(debug_mode=debug_mode, **kwargs) - apply_stylesheet(new_editor, theme="dark_amber.xml") + apply_stylesheet(new_ide, theme="dark_amber.xml") window.showMaximized() try: window.startup_setting() except Exception as error: print(repr(error)) - sys.exit(new_editor.exec()) + sys.exit(new_ide.exec()) diff --git a/automation_ide/automation_editor_ui/extend_multi_language/extend_english.py b/automation_ide/automation_editor_ui/extend_multi_language/extend_english.py index acc8053..05c319b 100644 --- a/automation_ide/automation_editor_ui/extend_multi_language/extend_english.py +++ b/automation_ide/automation_editor_ui/extend_multi_language/extend_english.py @@ -190,7 +190,39 @@ def update_english_word_dict(): "ai_code_review_gui_message_error": "Error", "ai_code_review_gui_status_accepted": "[Accepted]", "ai_code_review_gui_status_rejected": "[Rejected]", - "ai_code_review_gui_status_save_failed": "Save failed" + "ai_code_review_gui_status_save_failed": "Save failed", + # Prompt Editor + "prompt_editor_window_title": "Prompt Editor", + "prompt_editor_groupbox_edit_file_content": "Edit File Content", + "prompt_editor_button_create_file": "Create File", + "prompt_editor_button_save_file": "Save", + "prompt_editor_button_reload_file": "Reload", + "prompt_editor_msgbox_info_title": "Info", + "prompt_editor_msgbox_success_title": "Success", + "prompt_editor_msgbox_error_title": "Error", + "prompt_editor_msgbox_file_exists": "File {filename} already exists, no need to create", + "prompt_editor_msgbox_file_created": "File {filename} has been created", + "prompt_editor_msgbox_file_saved": "File {filename} saved", + "prompt_editor_msgbox_no_file_selected": "No file selected", + "prompt_editor_file_not_exist": "(File {filename} does not exist)", + # Extend Menu + "extend_tools_menu_tools_menu": "Tools", + "extend_tools_menu_tools_ssh_menu": "SSH", + "extend_tools_menu_tools_ai_menu": "AI", + "extend_tools_menu_ssh_client_tab_action": "SSH Client Tab", + "extend_tools_menu_ssh_client_tab_label": "SSH Client", + "extend_tools_menu_ai_code_review_tab_action": "AI Code-Review Tab", + "extend_tools_menu_ai_code_review_tab_label": "AI Code-Review", + "extend_tools_menu_prompt_editor_tab_action": "Prompt Editor", + "extend_tools_menu_prompt_editor_tab_label": "Prompt Editor", + "extend_tools_menu_dock_ssh_menu": "SSH", + "extend_tools_menu_dock_ai_menu": "AI", + "extend_tools_menu_ssh_client_dock_action": "SSH Client Dock", + "extend_tools_menu_ai_code_review_dock_action": "AI Code-Review Dock", + "extend_tools_menu_prompt_editor_dock_action": "Prompt Editor Dock", + "extend_tools_menu_ssh_client_dock_title": "SSH Client", + "extend_tools_menu_ai_code_review_dock_title": "AI Code-Review", + "extend_tools_menu_prompt_editor_dock_title": "PromptEditor", } ) diff --git a/automation_ide/automation_editor_ui/extend_multi_language/extend_traditional_chinese.py b/automation_ide/automation_editor_ui/extend_multi_language/extend_traditional_chinese.py index 9c1bfb9..447892f 100644 --- a/automation_ide/automation_editor_ui/extend_multi_language/extend_traditional_chinese.py +++ b/automation_ide/automation_editor_ui/extend_multi_language/extend_traditional_chinese.py @@ -190,6 +190,39 @@ def update_traditional_chinese_word_dict(): "ai_code_review_gui_message_error": "錯誤", "ai_code_review_gui_status_accepted": "[已接受]", "ai_code_review_gui_status_rejected": "[已拒絕]", - "ai_code_review_gui_status_save_failed": "儲存失敗" + "ai_code_review_gui_status_save_failed": "儲存失敗", + # Prompt Editor + "prompt_editor_window_title": "提示編輯器", + "prompt_editor_groupbox_edit_file_content": "編輯檔案內容", + "prompt_editor_button_create_file": "建立檔案", + "prompt_editor_button_save_file": "儲存", + "prompt_editor_button_reload_file": "重新載入", + "prompt_editor_msgbox_info_title": "資訊", + "prompt_editor_msgbox_success_title": "成功", + "prompt_editor_msgbox_error_title": "錯誤", + "prompt_editor_msgbox_file_exists": "檔案 {filename} 已存在,無需建立", + "prompt_editor_msgbox_file_created": "檔案 {filename} 已建立", + "prompt_editor_msgbox_file_saved": "檔案 {filename} 已儲存", + "prompt_editor_msgbox_no_file_selected": "尚未選擇檔案", + "prompt_editor_file_not_exist": "(檔案 {filename} 不存在)", + # Extend Menu + "extend_tools_menu_tools_menu": "工具", + "extend_tools_menu_tools_ssh_menu": "SSH", + "extend_tools_menu_tools_ai_menu": "AI", + "extend_tools_menu_ssh_client_tab_action": "SSH 用戶端分頁", + "extend_tools_menu_ssh_client_tab_label": "SSH 用戶端", + "extend_tools_menu_ai_code_review_tab_action": "AI 程式碼審查分頁", + "extend_tools_menu_ai_code_review_tab_label": "AI 程式碼審查", + "extend_tools_menu_prompt_editor_tab_action": "提示詞編輯器", + "extend_tools_menu_prompt_editor_tab_label": "提示詞編輯器", + "extend_tools_menu_dock_ssh_menu": "SSH", + "extend_tools_menu_dock_ai_menu": "AI", + "extend_tools_menu_ssh_client_dock_action": "SSH 用戶端停駐窗格", + "extend_tools_menu_ai_code_review_dock_action": "AI 程式碼審查停駐窗格", + "extend_tools_menu_prompt_editor_dock_action": "提示詞編輯器停駐窗格", + "extend_tools_menu_ssh_client_dock_title": "SSH 用戶端", + "extend_tools_menu_ai_code_review_dock_title": "AI 程式碼審查", + "extend_tools_menu_prompt_editor_dock_title": "提示詞編輯器", + } ) diff --git a/automation_ide/automation_editor_ui/menu/tools/tools_menu.py b/automation_ide/automation_editor_ui/menu/tools/tools_menu.py index bba0345..5d2cc02 100644 --- a/automation_ide/automation_editor_ui/menu/tools/tools_menu.py +++ b/automation_ide/automation_editor_ui/menu/tools/tools_menu.py @@ -3,11 +3,13 @@ from typing import TYPE_CHECKING from PySide6.QtGui import QAction, Qt +from je_editor import language_wrapper from je_editor.pyside_ui.main_ui.dock.destroy_dock import DestroyDock from je_editor.utils.logging.loggin_instance import jeditor_logger from automation_ide.automation_editor_ui.connect_gui.ssh.ssh_main_widget import SSHMainWidget from automation_ide.automation_editor_ui.connect_gui.url.ai_code_review_gui import AICodeReviewClient +from automation_ide.automation_editor_ui.prompt_edit_gui.main_prompt_edit_widget import PromptEditor if TYPE_CHECKING: from automation_ide.automation_editor_ui.editor_main.main_ui import AutomationEditor @@ -15,44 +17,83 @@ def build_tools_menu(ui_we_want_to_set: AutomationEditor): # Menus - ui_we_want_to_set.tools_menu = ui_we_want_to_set.menu.addMenu("Tools") - ui_we_want_to_set.tools_ssh_menu = ui_we_want_to_set.tools_menu.addMenu("SSH") - ui_we_want_to_set.tools_ai_menu = ui_we_want_to_set.tools_menu.addMenu("AI") + ui_we_want_to_set.tools_menu = ui_we_want_to_set.menu.addMenu(language_wrapper.language_word_dict.get( + "extend_tools_menu_tools_menu" + )) + ui_we_want_to_set.tools_ssh_menu = ui_we_want_to_set.tools_menu.addMenu(language_wrapper.language_word_dict.get( + "extend_tools_menu_tools_ssh_menu" + )) + ui_we_want_to_set.tools_ai_menu = ui_we_want_to_set.tools_menu.addMenu(language_wrapper.language_word_dict.get( + "extend_tools_menu_tools_ai_menu" + )) - ui_we_want_to_set.tools_ssh_client_tab_action = QAction("SSH Client Tab") + ui_we_want_to_set.tools_ssh_client_tab_action = QAction(language_wrapper.language_word_dict.get( + "extend_tools_menu_ssh_client_tab_action" + )) ui_we_want_to_set.tools_ssh_client_tab_action.triggered.connect(lambda: ui_we_want_to_set.tab_widget.addTab( - SSHMainWidget(), "SSH Client" + SSHMainWidget(), language_wrapper.language_word_dict.get("extend_tools_menu_ssh_client_tab_label") )) ui_we_want_to_set.tools_ssh_menu.addAction(ui_we_want_to_set.tools_ssh_client_tab_action) - ui_we_want_to_set.tools_ai_code_review_action = QAction("AI Code-Review Tab") + ui_we_want_to_set.tools_ai_code_review_action = QAction(language_wrapper.language_word_dict.get( + "extend_tools_menu_ai_code_review_tab_action" + )) ui_we_want_to_set.tools_ai_code_review_action.triggered.connect(lambda: ui_we_want_to_set.tab_widget.addTab( - AICodeReviewClient(), "AI Code-Review" + AICodeReviewClient(), language_wrapper.language_word_dict.get( + "extend_tools_menu_ai_code_review_tab_label" + ) )) ui_we_want_to_set.tools_ai_menu.addAction(ui_we_want_to_set.tools_ai_code_review_action) + ui_we_want_to_set.tools_ai_prompt_editor_action = QAction(language_wrapper.language_word_dict.get( + "extend_tools_menu_prompt_editor_tab_action" + )) + ui_we_want_to_set.tools_ai_prompt_editor_action.triggered.connect(lambda: ui_we_want_to_set.tab_widget.addTab( + PromptEditor(), language_wrapper.language_word_dict.get( + "extend_tools_menu_prompt_editor_tab_label" + ) + )) + ui_we_want_to_set.tools_ai_menu.addAction(ui_we_want_to_set.tools_ai_prompt_editor_action) + def extend_dock_menu(ui_we_want_to_set: AutomationEditor): # Sub menu ui_we_want_to_set.dock_ssh_menu = ui_we_want_to_set.dock_menu.addMenu( - "SSH" + language_wrapper.language_word_dict.get("extend_tools_menu_dock_ssh_menu") ) ui_we_want_to_set.dock_ai_menu = ui_we_want_to_set.dock_menu.addMenu( - "AI" + language_wrapper.language_word_dict.get("extend_tools_menu_dock_ai_menu") ) # SSH - ui_we_want_to_set.tools_ssh_client_dock_action = QAction("SSH Client Dock") + ui_we_want_to_set.tools_ssh_client_dock_action = QAction( + language_wrapper.language_word_dict.get("extend_tools_menu_ssh_client_dock_action") + ) ui_we_want_to_set.tools_ssh_client_dock_action.triggered.connect( - lambda: add_dock(ui_we_want_to_set, "SSH") + lambda: add_dock(ui_we_want_to_set, language_wrapper.language_word_dict.get( + "extend_tools_menu_dock_ssh_menu" + )) ) ui_we_want_to_set.dock_ssh_menu.addAction(ui_we_want_to_set.tools_ssh_client_dock_action) # AI - ui_we_want_to_set.tools_ai_code_review_dock_action = QAction("AI Code-Review Dock") + ui_we_want_to_set.tools_ai_code_review_dock_action = QAction(language_wrapper.language_word_dict.get( + "extend_tools_menu_ai_code_review_dock_action" + )) ui_we_want_to_set.tools_ai_code_review_dock_action.triggered.connect( - lambda: add_dock(ui_we_want_to_set, "AICodeReview") + lambda: add_dock(ui_we_want_to_set, language_wrapper.language_word_dict.get( + "extend_tools_menu_prompt_editor_dock_action" + )) ) ui_we_want_to_set.dock_ai_menu.addAction(ui_we_want_to_set.tools_ai_code_review_dock_action) + ui_we_want_to_set.tools_prompt_editor_dock_action = QAction(language_wrapper.language_word_dict.get( + "extend_tools_menu_prompt_editor_dock_action")) + ui_we_want_to_set.tools_prompt_editor_dock_action.triggered.connect( + lambda: add_dock(ui_we_want_to_set, language_wrapper.language_word_dict.get( + "extend_tools_menu_prompt_editor_dock_action" + )) + ) + ui_we_want_to_set.dock_ai_menu.addAction(ui_we_want_to_set.tools_prompt_editor_dock_action) + def add_dock(ui_we_want_to_set: AutomationEditor, widget_type: str = None): jeditor_logger.info("build_dock_menu.py add_dock_widget " f"ui_we_want_to_set: {ui_we_want_to_set} " @@ -63,11 +104,20 @@ def add_dock(ui_we_want_to_set: AutomationEditor, widget_type: str = None): dock_widget = DestroyDock() if widget_type == "SSH": - dock_widget.setWindowTitle("SSH Client") + dock_widget.setWindowTitle(language_wrapper.language_word_dict.get( + "extend_tools_menu_ssh_client_dock_title" + )) dock_widget.setWidget(SSHMainWidget()) elif widget_type == "AICodeReview": - dock_widget.setWindowTitle("AI Code-Review") + dock_widget.setWindowTitle(language_wrapper.language_word_dict.get( + "extend_tools_menu_ai_code_review_dock_title" + )) dock_widget.setWidget(AICodeReviewClient()) + elif widget_type == "PromptEditor": + dock_widget.setWindowTitle(language_wrapper.language_word_dict.get( + "extend_tools_menu_prompt_editor_dock_title" + )) + dock_widget.setWidget(PromptEditor()) # 如果成功建立了 widget,將其加到主視窗右側 Dock 區域 # If widget is created, add it to the right dock area of the main window diff --git a/automation_ide/automation_editor_ui/prompt_edit_gui/main_prompt_edit_widget.py b/automation_ide/automation_editor_ui/prompt_edit_gui/main_prompt_edit_widget.py index eaa0492..3c59665 100644 --- a/automation_ide/automation_editor_ui/prompt_edit_gui/main_prompt_edit_widget.py +++ b/automation_ide/automation_editor_ui/prompt_edit_gui/main_prompt_edit_widget.py @@ -1,11 +1,11 @@ import os -import sys from PySide6.QtCore import QFileSystemWatcher from PySide6.QtWidgets import ( - QApplication, QWidget, QVBoxLayout, QHBoxLayout, - QComboBox, QTextEdit, QLineEdit, QPushButton, QLabel, QGroupBox, QMessageBox + QWidget, QVBoxLayout, QHBoxLayout, + QComboBox, QTextEdit, QPushButton, QGroupBox, QMessageBox ) +from je_editor import language_wrapper from automation_ide.automation_editor_ui.prompt_edit_gui.prompt_templates.first_code_review import FIRST_CODE_REVIEW from automation_ide.automation_editor_ui.prompt_edit_gui.prompt_templates.first_summary_prompt import \ @@ -35,7 +35,9 @@ def __init__(self, prompt_files=None, parent=None): "total_summary.md": TOTAL_SUMMARY_TEMPLATE, } - self.setWindowTitle("Prompt Editor") # 視窗標題:Prompt 編輯器 + self.setWindowTitle(language_wrapper.language_word_dict.get( + "prompt_editor_window_title" + )) # 視窗標題:Prompt 編輯器 # --- Layouts (版面配置) --- main_layout = QVBoxLayout(self) @@ -43,45 +45,36 @@ def __init__(self, prompt_files=None, parent=None): editor_layout = QHBoxLayout() bottom_layout = QHBoxLayout() - # --- AI URL input box (AI URL 輸入框) --- - self.url_label = QLabel("AI URL:") - self.url_input = QLineEdit() - top_layout.addWidget(self.url_label) - top_layout.addWidget(self.url_input) - # --- ComboBox for selecting files (下拉選單選擇檔案) --- self.file_selector = QComboBox() self.file_selector.addItems(self.prompt_files) self.file_selector.currentIndexChanged.connect(self.load_file_content) # --- Left Editable panel (左邊編輯區塊) --- - self.left_editor = QTextEdit() - left_group = QGroupBox("Edit File Content") # 左邊編輯檔案內容 - left_layout = QVBoxLayout() - left_layout.addWidget(self.left_editor) - left_group.setLayout(left_layout) - - # --- Right Editable panel (右邊可編輯區塊) --- - self.editable_panel = QTextEdit() - editable_group = QGroupBox("Edit Prompt (Editable)") # 編輯 Prompt (可編輯) - editable_layout = QVBoxLayout() - editable_layout.addWidget(self.editable_panel) - editable_group.setLayout(editable_layout) - - editor_layout.addWidget(left_group, 1) - editor_layout.addWidget(editable_group, 1) + self.middle_editor = QTextEdit() + prompt_group = QGroupBox(language_wrapper.language_word_dict.get( + "prompt_editor_groupbox_edit_file_content" + )) # 左邊編輯檔案內容 + middle_layout = QVBoxLayout() + middle_layout.addWidget(self.middle_editor) + prompt_group.setLayout(middle_layout) - # --- Buttons --- - self.send_button = QPushButton("Send") - self.send_button.clicked.connect(self.send_prompt) + editor_layout.addWidget(prompt_group, 1) - self.create_button = QPushButton("Create File") + # --- Buttons --- + self.create_button = QPushButton(language_wrapper.language_word_dict.get( + "prompt_editor_button_create_file" + )) self.create_button.clicked.connect(self.create_file) - self.save_button = QPushButton("Save") + self.save_button = QPushButton(language_wrapper.language_word_dict.get( + "prompt_editor_button_save_file" + )) self.save_button.clicked.connect(self.save_file) - self.reload_button = QPushButton("Reload") + self.reload_button = QPushButton(language_wrapper.language_word_dict.get( + "prompt_editor_button_reload_file" + )) self.reload_button.clicked.connect(lambda: self.load_file_content(self.file_selector.currentIndex())) bottom_layout.addWidget(self.file_selector) @@ -89,7 +82,6 @@ def __init__(self, prompt_files=None, parent=None): bottom_layout.addWidget(self.reload_button) bottom_layout.addWidget(self.save_button) bottom_layout.addWidget(self.create_button) - bottom_layout.addWidget(self.send_button) # --- Combine layouts (組合版面配置) --- main_layout.addLayout(top_layout) @@ -110,22 +102,30 @@ def load_file_content(self, index): if os.path.exists(filename): with open(filename, "r", encoding="utf-8") as f: content = f.read() - self.left_editor.setPlainText(content) + self.middle_editor.setPlainText(content) else: - self.left_editor.setPlainText(f"(File {filename} does not exist)") + self.middle_editor.setPlainText(language_wrapper.language_word_dict.get( + "prompt_editor_file_not_exist" + ).format(filename=filename)) def create_file(self): """建立目前選擇的檔案,若不存在則用模板內容建立""" filename = self.current_file if os.path.exists(filename): - QMessageBox.information(self, "Info", f"File {filename} already exists, no need to create") + QMessageBox.information( + self, + language_wrapper.language_word_dict.get("prompt_editor_msgbox_info_title"), + language_wrapper.language_word_dict.get("prompt_editor_msgbox_file_exists").format(filename=filename)) return template_content = self.templates.get(filename, "") with open(filename, "w", encoding="utf-8") as f: f.write(template_content) - QMessageBox.information(self, "Success", f"File {filename} has been created") + QMessageBox.information( + self, + language_wrapper.language_word_dict.get("prompt_editor_msgbox_success_title"), + language_wrapper.language_word_dict.get("prompt_editor_msgbox_file_created").format(filename=filename)) self.load_file_content(self.file_selector.currentIndex()) def on_file_changed(self, path): @@ -136,32 +136,17 @@ def on_file_changed(self, path): def save_file(self): """將左邊編輯區內容儲存到目前檔案""" if not hasattr(self, "current_file"): - QMessageBox.warning(self, "Error", "No file selected") + QMessageBox.warning( + self, + language_wrapper.language_word_dict.get("prompt_editor_msgbox_error_title"), + language_wrapper.language_word_dict.get("prompt_editor_msgbox_no_file_selected")) return - content = self.left_editor.toPlainText() + content = self.middle_editor.toPlainText() with open(self.current_file, "w", encoding="utf-8") as f: f.write(content) - QMessageBox.information(self, "Success", f"File {self.current_file} saved") - - def send_prompt(self): - """模擬發送 prompt 到 AI URL""" - ai_url = self.url_input.text().strip() - prompt_text = self.editable_panel.toPlainText().strip() - - if not ai_url: - QMessageBox.warning(self, "Warning", "Please enter AI URL") - return - if not prompt_text: - QMessageBox.warning(self, "Warning", "Please enter the prompt to send") - return - - # 成功提示 - QMessageBox.information(self, "Sending Prompt", - f"Sending prompt to {ai_url}:\n\n{prompt_text}") - -if __name__ == "__main__": - app = QApplication(sys.argv) - editor = PromptEditor() - editor.showMaximized() - sys.exit(app.exec()) + QMessageBox.information( + self, + language_wrapper.language_word_dict.get("prompt_editor_msgbox_success_title"), + language_wrapper.language_word_dict.get("prompt_editor_msgbox_file_saved").format( + filename=self.current_file)) diff --git a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/first_code_review.py b/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/first_code_review.py index eb07aeb..75e74c9 100644 --- a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/first_code_review.py +++ b/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/first_code_review.py @@ -1 +1,23 @@ -FIRST_CODE_REVIEW = "" +FIRST_CODE_REVIEW = """ +# Code Review Template + +## PR Description +{pr_description}} + +## Review Rules +Please perform a first-step code review focusing on the following aspects: +1. Code readability (indentation, formatting, comments). +2. Clarity and descriptiveness of variable, function, and class names; avoid overly vague or cryptic naming. +3. Adherence to basic software engineering standards (modularity, maintainability, avoidance of duplicate code). +4. Identification of obvious logical errors or potential bugs. +5. Provide specific improvement suggestions with brief explanations. +6. Focus only on the most obvious issues and avoid deep analysis at this stage. + +Respond in a structured, bullet-point format, keeping the feedback concise and professional. + +## Code diff to review: +```diff +# Paste your code diff here +{code_diff} +``` +""" diff --git a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/first_summary_prompt.py b/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/first_summary_prompt.py index 517efcf..610e138 100644 --- a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/first_summary_prompt.py +++ b/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/first_summary_prompt.py @@ -1 +1,21 @@ -FIRST_SUMMARY_PROMPT = "" +FIRST_SUMMARY_PROMPT = """ +## PR Description +{pr_description}} + +## Summary Rules +Please generate a first-step Pull Request summary (PR Summary) focusing on: +1. Key changes: Briefly describe the core modifications or new features. +2. Impact scope: Identify affected modules, files, or functionalities. +3. Purpose of changes: Explain why these modifications are needed (e.g., bug fix, performance optimization, feature addition). +4. Risks and considerations: Highlight potential impacts on existing functionality or areas requiring extra testing. +5. Items to confirm: List specific points that reviewers should pay attention to or validate. +6. Avoid excessive technical detail; keep the summary at a high level for quick team understanding. + +Write in a structured, bullet-point format, keeping the summary concise and professional for quick team understanding. + +## Code diff to review: +```diff +# Paste your code diff here +{code_diff} +``` +""" diff --git a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/global_rule.py b/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/global_rule.py index c967395..e35e4ec 100644 --- a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/global_rule.py +++ b/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/global_rule.py @@ -1 +1,31 @@ -GLOBAL_RULE_TEMPLATE = "" \ No newline at end of file +GLOBAL_RULE_TEMPLATE = """ +Please conduct a code review according to the following global rules: + +1. Readability & Consistency + - Check indentation, formatting, and comments for clarity. + - Ensure code style follows team conventions (naming rules, formatting tools). + +2. Naming Conventions + - Variable, function, and class names must be descriptive and meaningful. + - Maintain semantic clarity and consistency across the codebase. + +3. Software Engineering Standards + - Code should be modular, maintainable, and testable. + - Avoid duplicate code; encourage refactoring and abstraction. + +4. Logic & Correctness + - Verify correctness of program logic and identify potential bugs. + - Check boundary conditions and exception handling. + +5. Performance & Security + - Assess for unnecessary performance bottlenecks. + - Review for security risks (e.g., input validation, resource management). + +6. Documentation & Testing + - Ensure necessary comments and documentation are present. + - Verify sufficient unit and integration tests are included. + +7. When scoring, balance conciseness with comprehensiveness; avoid penalizing completeness for being less concise.” + +Provide review feedback in a structured bullet-point format, keeping it professional, concise, and with actionable improvement suggestions. +""" diff --git a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/judge.py b/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/judge.py index f0a1655..5143cfd 100644 --- a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/judge.py +++ b/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/judge.py @@ -1 +1,38 @@ -JUDGE_TEMPLATE = "" \ No newline at end of file +JUDGE_TEMPLATE = """ +Please conduct a code review for the Pull Request using the following scoring mechanism: + +Score range: Minimum 1, Maximum 5. + +Six evaluation dimensions: +1. Readability + - 1: Code is hard to understand, lacks comments and consistency. + - 3: Code is generally clear, naming is reasonable, but improvements are needed. + - 5: Code is highly readable, well-structured, with complete naming and documentation. + +2. Maintainability + - 1: Code is tightly coupled, lacks modularity, and is difficult to maintain. + - 3: Code has basic modularity, maintainable but with duplication or potential issues. + - 5: Code is well-designed, modular, and easy to extend and maintain. + +3. Correctness + - 1: Contains obvious logical errors or bugs, insufficient testing. + - 3: Code is mostly correct, with minor edge cases unhandled. + - 5: Code is logically sound, thoroughly tested, and highly stable. + +4. Conciseness + - 1: Code is verbose, with unnecessary duplication. + - 3: Code is fairly concise but could be optimized further. + - 5: Code is highly concise, avoids redundancy, and is elegantly structured. + +5. Comprehensiveness + - 1: Missing essential functionality or tests, insufficient coverage. + - 3: Functionality and tests are mostly complete but with some gaps. + - 5: Functionality and tests are fully comprehensive, with complete documentation. + +6. Relevance + - 1: Changes do not align with requirements, unnecessary code included. + - 3: Changes mostly align with requirements but with minor deviations. + - 5: Changes fully align with requirements, precisely addressing the problem. + +Reviewers should assign a score (1–5) for each dimension, provide brief reasoning, and conclude with an average score and overall recommendation. +""" \ No newline at end of file diff --git a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/total_summary.py b/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/total_summary.py index d235c90..5b24e29 100644 --- a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/total_summary.py +++ b/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/total_summary.py @@ -1 +1,11 @@ -TOTAL_SUMMARY_TEMPLATE = "" \ No newline at end of file +TOTAL_SUMMARY_TEMPLATE = """ +Please generate the final code-review summary (PR Total Summary) for this Pull Request, covering: + +1. Overall conclusion: Briefly state the overall review outcome and whether it meets merge criteria. +2. Comprehensive evaluation: Summarize code quality, maintainability, and alignment with team standards. +3. Decision recommendation: Clearly indicate the final recommendation (e.g., approve merge, request changes, comment only). +4. Team follow-up: Suggest any necessary next steps (e.g., additional testing, documentation updates, performance improvements). +5. Do not repeat earlier details; concentrate solely on the final conclusion and recommendation. + +Keep the summary concise and professional, avoid repeating earlier review details, and focus on the final conclusion. +""" \ No newline at end of file diff --git a/automation_ide/utils/logging/__init__.py b/automation_ide/utils/logging/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/automation_ide/utils/logging/logger.py b/automation_ide/utils/logging/logger.py new file mode 100644 index 0000000..962763c --- /dev/null +++ b/automation_ide/utils/logging/logger.py @@ -0,0 +1,50 @@ +import logging +from logging.handlers import RotatingFileHandler + +# 設定 root logger 等級 Set root logger level +logging.root.setLevel(logging.DEBUG) + +# 建立 AutoControlGUI 專用 logger Create dedicated logger +automation_ide_logger = logging.getLogger("AutomationIDE") + +# 日誌格式 Formatter +formatter = logging.Formatter( + "%(asctime)s | %(name)s | %(levelname)s | %(message)s" +) + + +class AutomationIDELogger(RotatingFileHandler): + """ + AutoControlGUILoggingHandler + 自訂日誌處理器,繼承 RotatingFileHandler + - 支援檔案大小輪替 + - 預設輸出到 AutoControlGUI.log + """ + + def __init__( + self, + filename: str = "AutomationIDE.log", + mode: str = "w", + max_bytes: int = 1073741824, # 1GB + backup_count: int = 0, + ): + super().__init__( + filename=filename, + mode=mode, + maxBytes=max_bytes, + backupCount=backup_count, + ) + self.setFormatter(formatter) # 設定格式器 + self.setLevel(logging.DEBUG) # 設定等級 + + def emit(self, record: logging.LogRecord) -> None: + """ + Emit log record. + 輸出日誌紀錄 + """ + super().emit(record) + + +# 建立並加入檔案處理器 Add file handler to logger +file_handler = AutomationIDELogger() +automation_ide_logger.addHandler(file_handler) diff --git a/dev.toml b/dev.toml index d33f3f8..0d164fd 100644 --- a/dev.toml +++ b/dev.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" [project] name = "automation_ide_dev" -version = "0.0.66" +version = "0.0.67" authors = [ { name = "JE-Chen", email = "jechenmailman@gmail.com" }, ] diff --git a/exe/auto_py_to_exe_setting.json b/exe/auto_py_to_exe_setting.json index 836c356..f1a4bd8 100644 --- a/exe/auto_py_to_exe_setting.json +++ b/exe/auto_py_to_exe_setting.json @@ -15,11 +15,11 @@ }, { "optionDest": "console", - "value": false + "value": true }, { "optionDest": "icon_file", - "value": "C:/CodeWorkspace/Python/AutomationIDE/exe/je_driver_icon.ico" + "value": "C:/CodeWorkspace/Python/AutomationIDE/exe/automation_ide.ico" }, { "optionDest": "name", @@ -59,11 +59,7 @@ }, { "optionDest": "datas", - "value": "C:/CodeWorkspace/Python/AutomationIDE/exe/je_driver_icon.ico;." - }, - { - "optionDest": "datas", - "value": "C:/CodeWorkspace/Python/AutomationIDE/.venv/Lib/site-packages/ipython-8.32.0.dist-info;.ipython-8.32.0.dist-info/" + "value": "C:/CodeWorkspace/Python/AutomationIDE/.venv/Lib/site-packages/ipython-9.8.0.dist-info;ipython-9.8.0.dist-info/" }, { "optionDest": "datas", @@ -71,7 +67,7 @@ }, { "optionDest": "datas", - "value": "C:/CodeWorkspace/Python/AutomationIDE/.venv/Lib/site-packages/ipykernel-6.29.5.dist-info;ipykernel-6.29.5.dist-info/" + "value": "C:/CodeWorkspace/Python/AutomationIDE/.venv/Lib/site-packages/ipykernel-7.1.0.dist-info;ipykernel-7.1.0.dist-info/" }, { "optionDest": "datas", diff --git a/exe/automation_ide.ico b/exe/automation_ide.ico new file mode 100644 index 0000000..3c804ff Binary files /dev/null and b/exe/automation_ide.ico differ diff --git a/exe/je_driver_icon.ico b/exe/je_driver_icon.ico deleted file mode 100644 index 1d7e735..0000000 Binary files a/exe/je_driver_icon.ico and /dev/null differ diff --git a/pyproject.toml b/pyproject.toml index f99ea83..56463a8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" [project] name = "automation_ide" -version = "0.0.54" +version = "0.0.58" authors = [ { name = "JE-Chen", email = "jechenmailman@gmail.com" }, ] @@ -16,7 +16,7 @@ license-files = ["LICENSE"] dependencies = [ "je-editor", "je_auto_control", "je_web_runner", "je_load_density", "je_api_testka", "je-mail-thunder", - "automation-file", "PySide6==6.10.0", "test_pioneer", "paramiko" + "automation-file", "PySide6==6.10.1", "test_pioneer", "paramiko" ] classifiers = [ "Programming Language :: Python :: 3.10",