diff --git a/automation_ide/automation_editor_ui/prompt_edit_gui/__init__.py b/automation_ide/automation_editor_ui/extend_ai_gui/__init__.py similarity index 100% rename from automation_ide/automation_editor_ui/prompt_edit_gui/__init__.py rename to automation_ide/automation_editor_ui/extend_ai_gui/__init__.py diff --git a/automation_ide/automation_editor_ui/extend_ai_gui/ai_gui_global_variable.py b/automation_ide/automation_editor_ui/extend_ai_gui/ai_gui_global_variable.py new file mode 100644 index 0000000..1fff991 --- /dev/null +++ b/automation_ide/automation_editor_ui/extend_ai_gui/ai_gui_global_variable.py @@ -0,0 +1,44 @@ +from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.code_smell_detector import \ + CODE_SMELL_DETECTOR_TEMPLATE +from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.first_code_review import \ + FIRST_CODE_REVIEW_TEMPLATE +from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.first_summary_prompt import \ + FIRST_SUMMARY_TEMPLATE +from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.global_rule import \ + GLOBAL_RULE_TEMPLATE +from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.linter import \ + LINTER_TEMPLATE +from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.total_summary import \ + TOTAL_SUMMARY_TEMPLATE +from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.skills_prompt_templates.code_explainer import \ + CODE_EXPLAINER_TEMPLATE +from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.skills_prompt_templates.code_review import \ + CODE_REVIEW_SKILL_TEMPLATE + +COT_TEMPLATE_FILES = [ + "global_rule.md", + "first_summary_prompt.md", + "first_code_review.md", + "linter.md", + "code_smell_detector.md", + "total_summary.md", +] + +COT_TEMPLATE_RELATION = { + "global_rule.md": GLOBAL_RULE_TEMPLATE, + "first_summary_prompt.md": FIRST_SUMMARY_TEMPLATE, + "first_code_review.md": FIRST_CODE_REVIEW_TEMPLATE, + "linter.md": LINTER_TEMPLATE, + "code_smell_detector.md": CODE_SMELL_DETECTOR_TEMPLATE, + "total_summary.md": TOTAL_SUMMARY_TEMPLATE, +} + +SKILLS_TEMPLATE_FILES = [ + "code_review_skill.md", + "code_explainer_skill.md", +] + +SKILLS_TEMPLATE_RELATION = { + "code_review_skill.md": CODE_REVIEW_SKILL_TEMPLATE, + "code_explainer_skill.md": CODE_EXPLAINER_TEMPLATE +} diff --git a/automation_ide/automation_editor_ui/extend_ai_gui/cot_code_review_gui.py b/automation_ide/automation_editor_ui/extend_ai_gui/cot_code_review_gui.py new file mode 100644 index 0000000..014dde5 --- /dev/null +++ b/automation_ide/automation_editor_ui/extend_ai_gui/cot_code_review_gui.py @@ -0,0 +1,165 @@ +import sys + +import requests +from PySide6.QtCore import QThread, Signal +from PySide6.QtWidgets import ( + QApplication, QWidget, QVBoxLayout, QHBoxLayout, + QPushButton, QTextEdit, QLabel, QLineEdit, QComboBox, QMessageBox +) +from je_editor import language_wrapper + +from automation_ide.automation_editor_ui.extend_ai_gui.ai_gui_global_variable import COT_TEMPLATE_FILES, \ + COT_TEMPLATE_RELATION +from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.global_rule import \ + build_global_rule_template +from automation_ide.automation_editor_ui.extend_multi_language.update_language_dict import update_language_dict + + +# Worker Thread 負責傳送資料 +class SenderThread(QThread): + update_response = Signal(str, str) # (filename, response) + + def __init__(self, files: list, code: str, url: str): + super().__init__() + self.files = files + self.code = code + self.url = url + + def run(self): + code = self.code + first_code_review_result = None + first_summary_result = None + linter_result = None + code_smell_result = None + for file in self.files: + match file: + case "first_summary_prompt.md": + first_summary_prompt = COT_TEMPLATE_RELATION.get("first_summary_prompt.md") + prompt = build_global_rule_template( + prompt=first_summary_prompt.format(code_diff=code) + ) + case "first_code_review.md": + first_code_review_prompt = COT_TEMPLATE_RELATION.get("first_code_review.md") + prompt = build_global_rule_template( + prompt=first_code_review_prompt.format(code_diff=code) + ) + case "linter.md": + linter_prompt = COT_TEMPLATE_RELATION.get("linter.md") + prompt = build_global_rule_template( + prompt=linter_prompt.format(code_diff=code) + ) + case "code_smell_detector.md": + code_smell_detector_prompt = COT_TEMPLATE_RELATION.get("code_smell_detector.md") + prompt = build_global_rule_template( + prompt=code_smell_detector_prompt.format(code_diff=code) + ) + case "total_summary.md": + total_summary_prompt = COT_TEMPLATE_RELATION.get("total_summary.md") + prompt = build_global_rule_template( + prompt=total_summary_prompt.format( + first_code_review=first_code_review_result, + first_summary=first_summary_result, + linter_result=linter_result, + code_smell_result=code_smell_result, + code_diff=code, + ) + ) + case _: + continue + + try: + # 傳送到指定 URL + resp = requests.post(self.url, json={"prompt": prompt}) + reply_text = resp.text + match file: + case "first_summary_prompt.md": + first_summary_result = reply_text + case "first_code_review.md": + first_code_review_result = reply_text + case "linter.md": + linter_result = reply_text + case "code_smell_detector.md": + code_smell_result = reply_text + case _: + continue + except Exception as e: + reply_text = f"{language_wrapper.language_word_dict.get("cot_gui_error_sending")} {file} {e}" + + # 發送訊號更新 UI + self.update_response.emit(file, reply_text) + + +class CoTCodeReviewGUI(QWidget): + def __init__(self): + super().__init__() + self.setWindowTitle(language_wrapper.language_word_dict.get("cot_gui_window_title")) + + # 檔案清單 + self.files = COT_TEMPLATE_FILES + + # UI 元件 + layout = QVBoxLayout() + + # URL 輸入框 + url_layout = QHBoxLayout() + url_layout.addWidget(QLabel(language_wrapper.language_word_dict.get("cot_gui_label_api_url"))) + self.url_input = QLineEdit() + self.url_input.setPlaceholderText(language_wrapper.language_word_dict.get("cot_gui_placeholder_api_url")) + url_layout.addWidget(self.url_input) + layout.addLayout(url_layout) + + # 傳送資料區域 + self.code_paste_area = QTextEdit() + self.code_paste_area.setPlaceholderText( + language_wrapper.language_word_dict.get("cot_gui_placeholder_code_paste_area")) + layout.addWidget(QLabel(language_wrapper.language_word_dict.get("cot_gui_label_prompt_area"))) + layout.addWidget(self.code_paste_area) + + # 回傳區域 + self.response_selector = QComboBox() # 改用 ComboBox + self.response_view = QTextEdit() + self.response_view.setReadOnly(True) # 可複製但不可編輯 + + hbox_layout = QHBoxLayout() + hbox_layout.addWidget(self.response_selector, 2) + hbox_layout.addWidget(self.response_view, 5) + + layout.addWidget(QLabel(language_wrapper.language_word_dict.get("cot_gui_label_response_area"))) + layout.addLayout(hbox_layout) + + # 傳送按鈕 + self.send_button = QPushButton(language_wrapper.language_word_dict.get("cot_gui_button_send")) + layout.addWidget(self.send_button) + + self.setLayout(layout) + + # 綁定事件 + self.response_selector.currentTextChanged.connect(self.show_response) + self.send_button.clicked.connect(self.start_sending) + + # 儲存回覆 + self.responses = {} + + def show_response(self, filename): + if filename in self.responses: + self.response_view.setPlainText(self.responses[filename]) + + def start_sending(self): + # 取得 URL + url = self.url_input.text().strip() + if not url: + message_box = QMessageBox() + message_box.warning(self, "Warning", language_wrapper.language_word_dict.get("cot_gui_error_no_url")) + message_box.exec_() + return + + # 啟動傳送 Thread + self.thread = SenderThread(files=self.files, code=self.code_paste_area.toPlainText(), url=url) + self.thread.update_response.connect(self.handle_response) + self.thread.start() + + def handle_response(self, filename, response): + self.responses[filename] = response + self.response_selector.addItem(filename) # 加入 ComboBox + # 自動顯示最新回覆 + self.response_selector.setCurrentText(filename) diff --git a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/__init__.py b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/__init__.py similarity index 100% rename from automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/__init__.py rename to automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/__init__.py diff --git a/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/__init__.py b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/code_smell_detector.py b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/code_smell_detector.py new file mode 100644 index 0000000..ca8b14e --- /dev/null +++ b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/code_smell_detector.py @@ -0,0 +1,22 @@ +CODE_SMELL_DETECTOR_TEMPLATE = """ +You are a senior software engineer specializing in code quality reviews. +Carefully analyze the following code and identify all possible **code smells**. +Provide a structured and detailed output. + +### Output Requirements: +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.). +2. **Problem Location**: Point out the relevant code block or example. +3. **Detailed Explanation**: Explain why this is considered a code smell and what problems it may cause in terms of readability, maintainability, or scalability. +4. **Improvement Suggestions**: Provide specific refactoring or optimization recommendations that follow software engineering best practices. +5. **Priority Level**: Rank the severity as High, Medium, or Low to help developers decide the order of fixes. + +### Output Format: +- Code Smell Type: +- Problem Location: +- Detailed Explanation: +- Improvement Suggestions: +- Priority Level: + +### Code: +{code_diff} +""" \ No newline at end of file diff --git a/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_code_review.py b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_code_review.py new file mode 100644 index 0000000..d884a5b --- /dev/null +++ b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_code_review.py @@ -0,0 +1,17 @@ +FIRST_CODE_REVIEW_TEMPLATE = """ +# Code Review Template + +## Review Rules +Perform a first-step code review focusing on: +1. Code readability (indentation, formatting, comments). +2. Clarity and descriptiveness of variable, function, and class names; avoid 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 concise improvement suggestions with short explanations. +6. Focus only on the most obvious issues; avoid deep analysis at this stage. + +Respond in a structured bullet-point format, keeping feedback concise and professional. + +## Code diff +{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/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_summary_prompt.py similarity index 55% rename from automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/first_summary_prompt.py rename to automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_summary_prompt.py index 610e138..07d3e90 100644 --- a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/first_summary_prompt.py +++ b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_summary_prompt.py @@ -1,21 +1,17 @@ -FIRST_SUMMARY_PROMPT = """ -## PR Description -{pr_description}} +FIRST_SUMMARY_TEMPLATE = """ +# PR Summary Template ## Summary Rules -Please generate a first-step Pull Request summary (PR Summary) focusing on: +Generate a first-step Pull Request 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. +6. Avoid excessive technical detail; keep the summary high-level for quick team understanding. -Write in a structured, bullet-point format, keeping the summary concise and professional for quick team understanding. +Write in structured bullet points; keep concise and professional. -## Code diff to review: -```diff -# Paste your code diff here +## Code diff to review {code_diff} -``` """ diff --git a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/global_rule.py b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/global_rule.py similarity index 52% rename from automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/global_rule.py rename to automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/global_rule.py index e35e4ec..ba0392a 100644 --- a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/global_rule.py +++ b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/global_rule.py @@ -24,8 +24,36 @@ 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. +7. Scoring & Feedback Style + - Balance conciseness with comprehensiveness. + - Do not penalize completeness for being less concise. + +{rag_rules_section} +--- + +# Prompt Content +{prompt} +""" + +def build_global_rule_template(rag_rules=None, prompt=""): + if not rag_rules: + rag_rules_section = "" # 忽略 RAG Rules 區塊 + else: + if isinstance(rag_rules, list): + rag_rules_text = "".join(f" - {rule}" for rule in rag_rules) + else: + rag_rules_text = f" - {rag_rules}" + + rag_rules_section = f""" +8. RAG Rules (Retrieval-Augmented Guidance) + - Apply RAG-provided rules when available. + - If a rule conflicts or duplicates existing global rules, prioritize the RAG rule. + - Ensure integration of RAG rules maintains consistency with overall review standards. +{rag_rules_text} """ + + return GLOBAL_RULE_TEMPLATE.format( + rag_rules_section=rag_rules_section, + prompt=prompt + ) diff --git a/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/linter.py b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/linter.py new file mode 100644 index 0000000..182539c --- /dev/null +++ b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/linter.py @@ -0,0 +1,17 @@ +LINTER_TEMPLATE = """ +You are a strict code linter. +Your task is to analyze the given source code and produce structured linter_messages. +Follow these rules: + +1. Do not rewrite or fix the code — only report issues. +2. Each linter_message must include: + - rule_id: A short identifier for the rule violated (e.g., "no-unused-vars"). + - severity: One of ["error", "warning", "info"]. + - message: A clear explanation of the issue. + - line: The line number where the issue occurs. + - suggestion: A concise recommendation for improvement. +3. If no issues are found, return an empty list. + +Now analyze the following code: +{code_diff} +""" \ No newline at end of file diff --git a/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/total_summary.py b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/total_summary.py new file mode 100644 index 0000000..60be5ee --- /dev/null +++ b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/total_summary.py @@ -0,0 +1,66 @@ +TOTAL_SUMMARY_TEMPLATE = """ +# PR Total Summary Instructions + +You are a senior code reviewer generating the **final PR Total Summary**. +You MUST base your analysis **strictly and exclusively** on the information provided below. +Do NOT introduce assumptions, external standards, or unstated context. + +Your task is to synthesize all provided review artifacts into a single, well-reasoned conclusion. + +## Requirements + +- Use **all provided inputs** as evidence: + - First Code Review Result + - First Summary Result + - Linter Result + - Code Smell Result + - Code Diff +- The final summary must clearly reflect **actual findings** from the above inputs. +- Avoid generic statements such as “code quality is good” unless directly supported by the data. +- Do NOT repeat earlier comments verbatim; instead, **aggregate and interpret** them. +- If there are conflicting signals (e.g., linter passes but code smells exist), explicitly reconcile them. +- If critical issues exist, they must directly impact the final recommendation. + +## Output Format + +Respond in **structured bullet points**, professional and concise, covering only: + +1. **Overall conclusion** + - Does the PR meet merge criteria based on the evidence? + - Mention any blocking vs non-blocking concerns. + +2. **Comprehensive evaluation** + - Code quality and correctness (derived from review + diff) + - Maintainability and design concerns (derived from code smells / structure) + - Consistency with existing patterns or standards (only if inferable from the diff) + +3. **Final decision recommendation** + - One of: Approve merge / Request changes / Comment only + - Justify the decision using concrete findings. + +4. **Team follow-up (if applicable)** + - Specific, actionable next steps grounded in the findings + - Omit this section if no follow-up is needed. + +Constraints: +- Do NOT add new issues not present in the provided inputs. +- Do NOT speculate about runtime behavior or architecture beyond what the diff shows. +- Focus solely on final judgment, not detailed line-by-line critique. + +--- + +## First Code Review Result +{first_code_review} + +## First Summary Result +{first_summary} + +## Linter Result +{linter_result} + +## Code Smell Result +{code_smell_result} + +## Code Diff +{code_diff} +""" diff --git a/automation_ide/automation_editor_ui/prompt_edit_gui/main_prompt_edit_widget.py b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_prompt_editor_widget.py similarity index 65% rename from automation_ide/automation_editor_ui/prompt_edit_gui/main_prompt_edit_widget.py rename to automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_prompt_editor_widget.py index 3c59665..d4a41c3 100644 --- a/automation_ide/automation_editor_ui/prompt_edit_gui/main_prompt_edit_widget.py +++ b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/cot_prompt_editor_widget.py @@ -7,36 +7,20 @@ ) 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 \ - FIRST_SUMMARY_PROMPT -from automation_ide.automation_editor_ui.prompt_edit_gui.prompt_templates.global_rule import GLOBAL_RULE_TEMPLATE -from automation_ide.automation_editor_ui.prompt_edit_gui.prompt_templates.judge import JUDGE_TEMPLATE -from automation_ide.automation_editor_ui.prompt_edit_gui.prompt_templates.total_summary import TOTAL_SUMMARY_TEMPLATE +from automation_ide.automation_editor_ui.extend_ai_gui.ai_gui_global_variable import COT_TEMPLATE_FILES, \ + COT_TEMPLATE_RELATION -class PromptEditor(QWidget): +class CoTPromptEditor(QWidget): def __init__(self, prompt_files=None, parent=None): super().__init__(parent) - self.prompt_files = prompt_files or [ - "global_rule.md", - "first_summary_prompt.md", - "first_code_review.md", - "judge.md", - "total_summary.md" - ] + self.prompt_files = prompt_files or COT_TEMPLATE_FILES # 對應檔案名稱與模板內容 - self.templates = { - "global_rule.md": GLOBAL_RULE_TEMPLATE, - "first_summary_prompt.md": FIRST_SUMMARY_PROMPT, - "first_code_review.md": FIRST_CODE_REVIEW, - "judge.md": JUDGE_TEMPLATE, - "total_summary.md": TOTAL_SUMMARY_TEMPLATE, - } + self.templates = COT_TEMPLATE_RELATION self.setWindowTitle(language_wrapper.language_word_dict.get( - "prompt_editor_window_title" + "cot_cot_prompt_editor_window_title" )) # 視窗標題:Prompt 編輯器 # --- Layouts (版面配置) --- @@ -53,7 +37,7 @@ def __init__(self, prompt_files=None, parent=None): # --- Left Editable panel (左邊編輯區塊) --- self.middle_editor = QTextEdit() prompt_group = QGroupBox(language_wrapper.language_word_dict.get( - "prompt_editor_groupbox_edit_file_content" + "cot_prompt_editor_groupbox_edit_file_content" )) # 左邊編輯檔案內容 middle_layout = QVBoxLayout() middle_layout.addWidget(self.middle_editor) @@ -63,17 +47,17 @@ def __init__(self, prompt_files=None, parent=None): # --- Buttons --- self.create_button = QPushButton(language_wrapper.language_word_dict.get( - "prompt_editor_button_create_file" + "cot_prompt_editor_button_create_file" )) self.create_button.clicked.connect(self.create_file) self.save_button = QPushButton(language_wrapper.language_word_dict.get( - "prompt_editor_button_save_file" + "cot_prompt_editor_button_save_file" )) self.save_button.clicked.connect(self.save_file) self.reload_button = QPushButton(language_wrapper.language_word_dict.get( - "prompt_editor_button_reload_file" + "cot_prompt_editor_button_reload_file" )) self.reload_button.clicked.connect(lambda: self.load_file_content(self.file_selector.currentIndex())) @@ -105,7 +89,7 @@ def load_file_content(self, index): self.middle_editor.setPlainText(content) else: self.middle_editor.setPlainText(language_wrapper.language_word_dict.get( - "prompt_editor_file_not_exist" + "cot_prompt_editor_file_not_exist" ).format(filename=filename)) def create_file(self): @@ -114,8 +98,8 @@ def create_file(self): if os.path.exists(filename): 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)) + language_wrapper.language_word_dict.get("cot_prompt_editor_msgbox_info_title"), + language_wrapper.language_word_dict.get("cot_prompt_editor_msgbox_file_exists").format(filename=filename)) return template_content = self.templates.get(filename, "") @@ -124,8 +108,8 @@ def create_file(self): 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)) + language_wrapper.language_word_dict.get("cot_prompt_editor_msgbox_success_title"), + language_wrapper.language_word_dict.get("cot_prompt_editor_msgbox_file_created").format(filename=filename)) self.load_file_content(self.file_selector.currentIndex()) def on_file_changed(self, path): @@ -138,8 +122,8 @@ def save_file(self): if not hasattr(self, "current_file"): 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")) + language_wrapper.language_word_dict.get("cot_prompt_editor_msgbox_error_title"), + language_wrapper.language_word_dict.get("cot_cot_prompt_editor_msgbox_no_file_selected")) return content = self.middle_editor.toPlainText() @@ -147,6 +131,6 @@ def save_file(self): f.write(content) 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( + language_wrapper.language_word_dict.get("cot_prompt_editor_msgbox_success_title"), + language_wrapper.language_word_dict.get("cot_prompt_editor_msgbox_file_saved").format( filename=self.current_file)) diff --git a/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_editor_widget.py b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_editor_widget.py new file mode 100644 index 0000000..30d5de4 --- /dev/null +++ b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_editor_widget.py @@ -0,0 +1,136 @@ +import os + +from PySide6.QtCore import QFileSystemWatcher +from PySide6.QtWidgets import ( + QWidget, QVBoxLayout, QHBoxLayout, + QComboBox, QTextEdit, QPushButton, QGroupBox, QMessageBox +) +from je_editor import language_wrapper + +from automation_ide.automation_editor_ui.extend_ai_gui.ai_gui_global_variable import SKILLS_TEMPLATE_FILES, \ + SKILLS_TEMPLATE_RELATION + + +class SkillPromptEditor(QWidget): + def __init__(self, skill_files=None, parent=None): + super().__init__(parent) + self.skill_files = skill_files or SKILLS_TEMPLATE_FILES + + # 對應檔案名稱與模板內容 + self.templates = SKILLS_TEMPLATE_RELATION + + self.setWindowTitle(language_wrapper.language_word_dict.get( + "skill_prompt_editor_window_title" + )) # 視窗標題:Skill Prompt 編輯器 + + # --- Layouts --- + main_layout = QVBoxLayout(self) + editor_layout = QHBoxLayout() + bottom_layout = QHBoxLayout() + + # --- ComboBox for selecting files --- + self.file_selector = QComboBox() + self.file_selector.addItems(self.skill_files) + self.file_selector.currentIndexChanged.connect(self.load_file_content) + + # --- Editable panel --- + self.middle_editor = QTextEdit() + skill_group = QGroupBox(language_wrapper.language_word_dict.get( + "skill_prompt_editor_groupbox_edit_file_content" + )) + middle_layout = QVBoxLayout() + middle_layout.addWidget(self.middle_editor) + skill_group.setLayout(middle_layout) + + editor_layout.addWidget(skill_group, 1) + + # --- Buttons --- + self.create_button = QPushButton(language_wrapper.language_word_dict.get( + "skill_prompt_editor_button_create_file" + )) + self.create_button.clicked.connect(self.create_file) + + self.save_button = QPushButton(language_wrapper.language_word_dict.get( + "skill_prompt_editor_button_save_file" + )) + self.save_button.clicked.connect(self.save_file) + + self.reload_button = QPushButton(language_wrapper.language_word_dict.get( + "skill_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) + bottom_layout.addStretch() + bottom_layout.addWidget(self.reload_button) + bottom_layout.addWidget(self.save_button) + bottom_layout.addWidget(self.create_button) + + # --- Combine layouts --- + main_layout.addLayout(editor_layout) + main_layout.addLayout(bottom_layout) + + # --- FileSystemWatcher --- + self.watcher = QFileSystemWatcher(self.skill_files) + self.watcher.fileChanged.connect(self.on_file_changed) + + # 預設載入第一個檔案 + self.load_file_content(0) + + def load_file_content(self, index): + """載入選擇的檔案內容到編輯區""" + filename = self.skill_files[index] + self.current_file = filename + if os.path.exists(filename): + with open(filename, "r", encoding="utf-8") as f: + content = f.read() + self.middle_editor.setPlainText(content) + else: + self.middle_editor.setPlainText(language_wrapper.language_word_dict.get( + "skill_prompt_editor_file_not_exist" + ).format(filename=filename)) + + def create_file(self): + """建立目前選擇的檔案,若不存在則用模板內容建立""" + filename = self.current_file + if os.path.exists(filename): + QMessageBox.information( + self, + language_wrapper.language_word_dict.get("skill_prompt_editor_msgbox_info_title"), + language_wrapper.language_word_dict.get("skill_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, + language_wrapper.language_word_dict.get("skill_prompt_editor_msgbox_success_title"), + language_wrapper.language_word_dict.get("skill_prompt_editor_msgbox_file_created").format( + filename=filename)) + self.load_file_content(self.file_selector.currentIndex()) + + def on_file_changed(self, path): + """當檔案被外部修改時即時更新""" + if path == self.current_file: + self.load_file_content(self.file_selector.currentIndex()) + + def save_file(self): + """將編輯區內容儲存到目前檔案""" + if not hasattr(self, "current_file"): + QMessageBox.warning( + self, + language_wrapper.language_word_dict.get("skill_prompt_editor_msgbox_error_title"), + language_wrapper.language_word_dict.get("skill_prompt_editor_msgbox_no_file_selected")) + return + + content = self.middle_editor.toPlainText() + with open(self.current_file, "w", encoding="utf-8") as f: + f.write(content) + QMessageBox.information( + self, + language_wrapper.language_word_dict.get("skill_prompt_editor_msgbox_success_title"), + language_wrapper.language_word_dict.get("skill_prompt_editor_msgbox_file_saved").format( + filename=self.current_file)) diff --git a/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/__init__.py b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_explainer.py b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_explainer.py new file mode 100644 index 0000000..20095d1 --- /dev/null +++ b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_explainer.py @@ -0,0 +1,21 @@ +CODE_EXPLAINER_TEMPLATE = """ +You are a senior software engineer and educator. Explain the following code clearly and in detail. + +Focus on: +- What the code does (purpose). +- How it works (step-by-step flow, inputs/outputs). +- Key functions, classes, or modules. +- Assumptions, edge cases, and possible errors. +- Performance or security concerns. +- Suggested improvements. + +Format: +- Title: one-line summary. +- Overview: short description. +- Detailed explanation: bullet points for flow and components. +- Improvements: concise list with rationale. +- Example usage if relevant. + +Code: +{code_diff} +""" \ No newline at end of file diff --git a/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_review.py b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_review.py new file mode 100644 index 0000000..b1b8b4b --- /dev/null +++ b/automation_ide/automation_editor_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_review.py @@ -0,0 +1,37 @@ +CODE_REVIEW_SKILL_TEMPLATE = """ +You are an expert software reviewer. Your task is to analyze one or more code diffs from a Pull Request (PR). +The input may contain multiple `code_diff` sections placed in different positions. + +For each diff, perform the following analysis and **always output results in three distinct sections**: + +--- + +### 1. **Summary** +- Explain the purpose and scope of the changes. +- Highlight affected files, functions, or modules. +- Provide a plain-language explanation for non-experts. + +--- + +### 2. **Linting Issues** +- Check the code against style and formatting rules. +- List violations clearly, with file and line references if possible. +- Suggest corrections following best practices. + +--- + +### 3. **Code Smells** +- Identify potential maintainability issues (duplication, long functions, poor naming, tight coupling). +- Explain why each issue is problematic. +- Recommend improvements or refactoring strategies. + +--- + +## Code diff +{code_diff} + +### Output Format +- Group results by diff: e.g., **Diff #1**, **Diff #2**, etc. +- Within each diff, strictly divide output into the three sections: **Summary**, **Linting Issues**, **Code Smells**. +- Present findings in bullet points or tables for readability. +""" \ No newline at end of file diff --git a/automation_ide/automation_editor_ui/extend_ai_gui/skills_send_gui.py b/automation_ide/automation_editor_ui/extend_ai_gui/skills_send_gui.py new file mode 100644 index 0000000..0a2e618 --- /dev/null +++ b/automation_ide/automation_editor_ui/extend_ai_gui/skills_send_gui.py @@ -0,0 +1,98 @@ +import sys +import requests +from PySide6.QtWidgets import ( + QApplication, QWidget, QVBoxLayout, QLineEdit, + QTextEdit, QPushButton, QLabel, QComboBox +) +from PySide6.QtCore import QThread, Signal +from je_editor import language_wrapper + +from automation_ide.automation_editor_ui.extend_ai_gui.ai_gui_global_variable import SKILLS_TEMPLATE_FILES + + +class RequestThread(QThread): + finished = Signal(str) # 成功或錯誤訊息 + error = Signal(str) + + def __init__(self, api_url, code_text): + super().__init__() + self.api_url = api_url + self.code_text = code_text + + def run(self): + try: + response = requests.post(self.api_url, json={"code": self.code_text}) + if response.status_code == 200: + self.finished.emit(response.text) + else: + self.finished.emit( + language_wrapper.language_word_dict.get( + "skills_error_status").format(status_code=response.status_code, text=response.text)) + except Exception as e: + self.error.emit(language_wrapper.language_word_dict.get("skills_exception").format(error=str(e))) + + +class SkillsSendGUI(QWidget): + def __init__(self): + super().__init__() + + layout = QVBoxLayout() + + # API URL 輸入框 + self.api_url_label = QLabel(language_wrapper.language_word_dict.get("skills_api_url_label")) + self.api_url_input = QLineEdit() + self.api_url_input.setPlaceholderText(language_wrapper.language_word_dict.get("skills_api_url_placeholder")) + layout.addWidget(self.api_url_label) + layout.addWidget(self.api_url_input) + + # Prompt 選擇下拉選單 + self.prompt_select_label = QLabel(language_wrapper.language_word_dict.get("skills_prompt_select_label")) + self.prompt_select = QComboBox() + self.prompt_select.addItems(SKILLS_TEMPLATE_FILES) + layout.addWidget(self.prompt_select_label) + layout.addWidget(self.prompt_select) + + # Prompt 輸入區域 + self.prompt_label = QLabel(language_wrapper.language_word_dict.get("skills_prompt_label")) + self.prompt_input = QTextEdit() + layout.addWidget(self.prompt_label) + layout.addWidget(self.prompt_input) + + # 傳送按鈕 + self.send_button = QPushButton(language_wrapper.language_word_dict.get("skills_send_button")) + self.send_button.clicked.connect(self.send_prompt) + layout.addWidget(self.send_button) + + # 回傳結果顯示區域 + self.response_label = QLabel(language_wrapper.language_word_dict.get("skills_response_label")) + self.response_output = QTextEdit() + self.response_output.setReadOnly(True) + layout.addWidget(self.response_label) + layout.addWidget(self.response_output) + + self.setLayout(layout) + + self.thread = None # 保存執行緒 + + def send_prompt(self): + api_url = self.api_url_input.text().strip() + prompt_text = self.prompt_input.toPlainText().strip() + + if not api_url or not prompt_text: + self.response_output.setPlainText(language_wrapper.language_word_dict.get("skills_missing_input")) + return + + # 顯示「產生中」 + self.response_output.setPlainText(language_wrapper.language_word_dict.get("skills_generating")) + + # 啟動 QThread + self.thread = RequestThread(api_url, prompt_text) + self.thread.finished.connect(self.on_finished) + self.thread.error.connect(self.on_error) + self.thread.start() + + def on_finished(self, result): + self.response_output.setPlainText(result) + + def on_error(self, error_msg): + self.response_output.setPlainText(error_msg) 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 05c319b..f0d9fb5 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 @@ -191,20 +191,34 @@ def update_english_word_dict(): "ai_code_review_gui_status_accepted": "[Accepted]", "ai_code_review_gui_status_rejected": "[Rejected]", "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)", + # CoT Prompt Editor + "cot_prompt_editor_window_title": "CoT Prompt Editor", + "cot_prompt_editor_groupbox_edit_file_content": "Edit File Content", + "cot_prompt_editor_button_create_file": "Create File", + "cot_prompt_editor_button_save_file": "Save", + "cot_prompt_editor_button_reload_file": "Reload", + "cot_prompt_editor_msgbox_info_title": "Info", + "cot_prompt_editor_msgbox_success_title": "Success", + "cot_prompt_editor_msgbox_error_title": "Error", + "cot_prompt_editor_msgbox_file_exists": "File {filename} already exists, no need to create", + "cot_prompt_editor_msgbox_file_created": "File {filename} has been created", + "cot_prompt_editor_msgbox_file_saved": "File {filename} saved", + "cot_prompt_editor_msgbox_no_file_selected": "No file selected", + "cot_prompt_editor_file_not_exist": "(File {filename} does not exist)", + # Skill Prompt Editor + "skill_prompt_editor_window_title": "Skill Prompt Editor", + "skill_prompt_editor_groupbox_edit_file_content": "Edit File Content", + "skill_prompt_editor_button_create_file": "Create File", + "skill_prompt_editor_button_save_file": "Save", + "skill_prompt_editor_button_reload_file": "Reload", + "skill_prompt_editor_msgbox_info_title": "Info", + "skill_prompt_editor_msgbox_success_title": "Success", + "skill_prompt_editor_msgbox_error_title": "Error", + "skill_prompt_editor_msgbox_file_exists": "File {filename} already exists, no need to create", + "skill_prompt_editor_msgbox_file_created": "File {filename} has been created", + "skill_prompt_editor_msgbox_file_saved": "File {filename} saved", + "skill_prompt_editor_msgbox_no_file_selected": "No file selected", + "skill_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", @@ -213,16 +227,46 @@ def update_english_word_dict(): "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_cot_prompt_editor_tab_action": "CoT Prompt Editor", + "extend_tools_menu_cot_prompt_editor_tab_label": "CoT Prompt Editor", + "extend_tools_menu_skill_prompt_editor_tab_action": "Skill Prompt Editor", + "extend_tools_menu_skill_prompt_editor_tab_label": "Skill Prompt Editor", + "extend_tools_menu_skill_prompt_send_tab_label": "Skill Send GUI", "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_cot_prompt_editor_dock_action": "CoT Prompt Editor Dock", + "extend_tools_menu_skill_prompt_editor_dock_action": "Skill 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", - + "extend_tools_menu_cot_prompt_editor_dock_title": "CoT PromptEditor", + "extend_tools_menu_skill_prompt_editor_dock_title": "Skill PromptEditor", + "extend_tools_menu_skill_prompt_send_dock_action": "Skill Prompt Dock", + "extend_tools_menu_skill_prompt_send_dock_title": "Skill Send GUI", + # CoT code-review GUI + "cot_gui_window_title": "Prompt Sender UI", + "cot_gui_label_api_url": "API URL:", + "cot_gui_placeholder_api_url": "Please enter the API URL to send, e.g. http://127.0.0.1:5000/api", + "cot_gui_placeholder_code_paste_area": "You can put the code to be sent", + "cot_gui_label_prompt_area": "Prompt Area", + "cot_gui_label_response_area": "Response Area", + "cot_gui_button_send": "Start Sending", + "cot_gui_error_read_file": "Unable to read file:", + "cot_gui_error_no_url": "Please enter the API URL first!", + "cot_gui_error_sending": "Error sending:", + # Skills GUI + "skills_finished_signal": "Success or error message", + "skills_error_signal": "Exception occurred", + "skills_error_status": "Error: {status_code}\n{text}", + "skills_exception": "Exception occurred: {error}", + "skills_api_url_label": "LLM API URL:", + "skills_api_url_placeholder": "Enter the API URL to send, e.g. http://127.0.0.1:5000/api", + "skills_prompt_select_label": "Select Prompt Template:", + "skills_prompt_label": "Prompt:", + "skills_send_button": "Send", + "skills_response_label": "Response:", + "skills_missing_input": "Please enter API URL and Prompt", + "skills_generating": "Generating...", } ) 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 447892f..820b751 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 @@ -191,20 +191,34 @@ def update_traditional_chinese_word_dict(): "ai_code_review_gui_status_accepted": "[已接受]", "ai_code_review_gui_status_rejected": "[已拒絕]", "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} 不存在)", + # Cot Prompt Editor + "cot_prompt_editor_window_title": "CoT 提示編輯器", + "cot_prompt_editor_groupbox_edit_file_content": "編輯檔案內容", + "cot_prompt_editor_button_create_file": "建立檔案", + "cot_prompt_editor_button_save_file": "儲存", + "cot_prompt_editor_button_reload_file": "重新載入", + "cot_prompt_editor_msgbox_info_title": "資訊", + "cot_prompt_editor_msgbox_success_title": "成功", + "cot_prompt_editor_msgbox_error_title": "錯誤", + "cot_prompt_editor_msgbox_file_exists": "檔案 {filename} 已存在,無需建立", + "cot_prompt_editor_msgbox_file_created": "檔案 {filename} 已建立", + "cot_prompt_editor_msgbox_file_saved": "檔案 {filename} 已儲存", + "cot_prompt_editor_msgbox_no_file_selected": "尚未選擇檔案", + "cot_prompt_editor_file_not_exist": "(檔案 {filename} 不存在)", + # Skill Prompt Editor + "skill_prompt_editor_window_title": "技能提示編輯器", + "skill_prompt_editor_groupbox_edit_file_content": "編輯檔案內容", + "skill_prompt_editor_button_create_file": "建立檔案", + "skill_prompt_editor_button_save_file": "儲存", + "skill_prompt_editor_button_reload_file": "重新載入", + "skill_prompt_editor_msgbox_info_title": "資訊", + "skill_prompt_editor_msgbox_success_title": "成功", + "skill_prompt_editor_msgbox_error_title": "錯誤", + "skill_prompt_editor_msgbox_file_exists": "檔案 {filename} 已存在,無需建立", + "skill_prompt_editor_msgbox_file_created": "檔案 {filename} 已建立", + "skill_prompt_editor_msgbox_file_saved": "檔案 {filename} 已儲存", + "skill_prompt_editor_msgbox_no_file_selected": "未選擇檔案", + "skill_prompt_editor_file_not_exist": "(檔案 {filename} 不存在)", # Extend Menu "extend_tools_menu_tools_menu": "工具", "extend_tools_menu_tools_ssh_menu": "SSH", @@ -213,16 +227,46 @@ def update_traditional_chinese_word_dict(): "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_cot_prompt_editor_tab_action": "CoT 提示詞編輯器", + "extend_tools_menu_cot_prompt_editor_tab_label": "CoT 提示詞編輯器", + "extend_tools_menu_skill_prompt_editor_tab_action": "Skill 提示詞編輯器", + "extend_tools_menu_skill_prompt_editor_tab_label": "Skill 提示詞編輯器", + "extend_tools_menu_skill_prompt_send_tab_label": "Skill 提示詞傳送 GUI", "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_cot_prompt_editor_dock_action": "CoT 提示詞編輯器停駐窗格", + "extend_tools_menu_skill_prompt_editor_dock_action": "Skill 提示詞編輯器停駐窗格", "extend_tools_menu_ssh_client_dock_title": "SSH 用戶端", "extend_tools_menu_ai_code_review_dock_title": "AI 程式碼審查", - "extend_tools_menu_prompt_editor_dock_title": "提示詞編輯器", - + "extend_tools_menu_cot_prompt_editor_dock_title": "CoT 提示詞編輯器", + "extend_tools_menu_skill_prompt_editor_dock_title": "Skill 提示詞編輯器", + "extend_tools_menu_skill_prompt_send_dock_action": "Skill Prompt 傳送停駐窗格", + "extend_tools_menu_skill_prompt_send_dock_title": "Skill 提示詞傳送 GUI", + # CoT code-review GUI + "cot_gui_window_title": "Prompt Sender UI", + "cot_gui_label_api_url": "API URL:", + "cot_gui_placeholder_api_url": "請輸入要傳送的 API URL,例如 http://127.0.0.1:5000/api", + "cot_gui_placeholder_code_paste_area": "這裡會顯示要傳送的 Prompt 內容", + "cot_gui_label_prompt_area": "傳送資料區域", + "cot_gui_label_response_area": "回傳區域", + "cot_gui_button_send": "開始傳送", + "cot_gui_error_read_file": "無法讀取檔案:", + "cot_gui_error_no_url": "請先輸入 API URL!", + "cot_gui_error_sending": "Error sending:", + # Skills GUI + "skills_finished_signal": "成功或錯誤訊息", + "skills_error_signal": "發生例外", + "skills_error_status": "錯誤: {status_code}\n{text}", + "skills_exception": "發生例外: {error}", + "skills_api_url_label": "LLM API URL:", + "skills_api_url_placeholder": "請輸入要傳送的 API URL,例如 http://127.0.0.1:5000/api", + "skills_prompt_select_label": "選擇 Prompt 範本:", + "skills_prompt_label": "Prompt:", + "skills_send_button": "傳送", + "skills_response_label": "回傳結果:", + "skills_missing_input": "請輸入 API URL 和 Prompt", + "skills_generating": "產生中...", } ) 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 5d2cc02..b71ea7f 100644 --- a/automation_ide/automation_editor_ui/menu/tools/tools_menu.py +++ b/automation_ide/automation_editor_ui/menu/tools/tools_menu.py @@ -5,11 +5,14 @@ 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 je_editor 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 +from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.cot_prompt_editor_widget import CoTPromptEditor +from automation_ide.automation_editor_ui.extend_ai_gui.prompt_edit_gui.skills_prompt_editor_widget import \ + SkillPromptEditor +from automation_ide.automation_editor_ui.extend_ai_gui.skills_send_gui import SkillsSendGUI if TYPE_CHECKING: from automation_ide.automation_editor_ui.editor_main.main_ui import AutomationEditor @@ -45,15 +48,35 @@ def build_tools_menu(ui_we_want_to_set: AutomationEditor): )) 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_cot_prompt_editor_action = QAction(language_wrapper.language_word_dict.get( + "extend_tools_menu_cot_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_cot_prompt_editor_action.triggered.connect(lambda: ui_we_want_to_set.tab_widget.addTab( + CoTPromptEditor(), language_wrapper.language_word_dict.get( + "extend_tools_menu_cot_prompt_editor_tab_label" ) )) - ui_we_want_to_set.tools_ai_menu.addAction(ui_we_want_to_set.tools_ai_prompt_editor_action) + ui_we_want_to_set.tools_ai_menu.addAction(ui_we_want_to_set.tools_ai_cot_prompt_editor_action) + + ui_we_want_to_set.tools_ai_skill_prompt_editor_action = QAction(language_wrapper.language_word_dict.get( + "extend_tools_menu_skill_prompt_editor_tab_action" + )) + ui_we_want_to_set.tools_ai_skill_prompt_editor_action.triggered.connect(lambda: ui_we_want_to_set.tab_widget.addTab( + SkillPromptEditor(), language_wrapper.language_word_dict.get( + "extend_tools_menu_skill_prompt_editor_tab_label" + ) + )) + ui_we_want_to_set.tools_ai_menu.addAction(ui_we_want_to_set.tools_ai_skill_prompt_editor_action) + + ui_we_want_to_set.tools_ai_skill_send_action = QAction(language_wrapper.language_word_dict.get( + "extend_tools_menu_skill_prompt_send_tab_label" + )) + ui_we_want_to_set.tools_ai_skill_send_action.triggered.connect(lambda: ui_we_want_to_set.tab_widget.addTab( + SkillsSendGUI(), language_wrapper.language_word_dict.get( + "extend_tools_menu_skill_prompt_send_tab_label" + ) + )) + ui_we_want_to_set.tools_ai_menu.addAction(ui_we_want_to_set.tools_ai_skill_send_action) def extend_dock_menu(ui_we_want_to_set: AutomationEditor): @@ -69,30 +92,34 @@ def extend_dock_menu(ui_we_want_to_set: AutomationEditor): 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, language_wrapper.language_word_dict.get( - "extend_tools_menu_dock_ssh_menu" - )) - ) + lambda: add_dock(ui_we_want_to_set, "SSH")) 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(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, language_wrapper.language_word_dict.get( - "extend_tools_menu_prompt_editor_dock_action" - )) - ) + lambda: add_dock(ui_we_want_to_set, "AICodeReview")) 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) + ui_we_want_to_set.tools_cot_prompt_editor_dock_action = QAction(language_wrapper.language_word_dict.get( + "extend_tools_menu_cot_prompt_editor_dock_action")) + ui_we_want_to_set.tools_cot_prompt_editor_dock_action.triggered.connect( + lambda: add_dock(ui_we_want_to_set, "CoTPromptEditor")) + ui_we_want_to_set.dock_ai_menu.addAction(ui_we_want_to_set.tools_cot_prompt_editor_dock_action) + + ui_we_want_to_set.tools_skill_prompt_editor_dock_action = QAction(language_wrapper.language_word_dict.get( + "extend_tools_menu_skill_prompt_editor_dock_action")) + ui_we_want_to_set.tools_skill_prompt_editor_dock_action.triggered.connect( + lambda: add_dock(ui_we_want_to_set, "SkillPromptEditor")) + ui_we_want_to_set.dock_ai_menu.addAction(ui_we_want_to_set.tools_skill_prompt_editor_dock_action) + + ui_we_want_to_set.tools_skill_send_dock_action = QAction(language_wrapper.language_word_dict.get( + "extend_tools_menu_skill_prompt_send_dock_action")) + ui_we_want_to_set.tools_skill_send_dock_action.triggered.connect( + lambda: add_dock(ui_we_want_to_set, "SkillSendGUI")) + ui_we_want_to_set.dock_ai_menu.addAction(ui_we_want_to_set.tools_skill_send_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 " @@ -113,11 +140,21 @@ def add_dock(ui_we_want_to_set: AutomationEditor, widget_type: str = None): "extend_tools_menu_ai_code_review_dock_title" )) dock_widget.setWidget(AICodeReviewClient()) - elif widget_type == "PromptEditor": + elif widget_type == "CoTPromptEditor": + dock_widget.setWindowTitle(language_wrapper.language_word_dict.get( + "extend_tools_menu_cot_prompt_editor_dock_title" + )) + dock_widget.setWidget(CoTPromptEditor()) + elif widget_type == "SkillPromptEditor": + dock_widget.setWindowTitle(language_wrapper.language_word_dict.get( + "extend_tools_menu_skill_prompt_editor_dock_title" + )) + dock_widget.setWidget(SkillPromptEditor()) + elif widget_type == "SkillSendGUI": dock_widget.setWindowTitle(language_wrapper.language_word_dict.get( - "extend_tools_menu_prompt_editor_dock_title" + "extend_tools_menu_skill_prompt_send_dock_title" )) - dock_widget.setWidget(PromptEditor()) + dock_widget.setWidget(SkillsSendGUI()) # 如果成功建立了 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/prompt_templates/first_code_review.py b/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/first_code_review.py deleted file mode 100644 index 75e74c9..0000000 --- a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/first_code_review.py +++ /dev/null @@ -1,23 +0,0 @@ -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/judge.py b/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/judge.py deleted file mode 100644 index 5143cfd..0000000 --- a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/judge.py +++ /dev/null @@ -1,38 +0,0 @@ -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 deleted file mode 100644 index 5b24e29..0000000 --- a/automation_ide/automation_editor_ui/prompt_edit_gui/prompt_templates/total_summary.py +++ /dev/null @@ -1,11 +0,0 @@ -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/pyproject.toml b/pyproject.toml index 56463a8..37c7fc5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,12 +1,12 @@ -# Rename to build stable version -# This is stable version +# Rename to dev version +# This is dev version [build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] -name = "automation_ide" -version = "0.0.58" +name = "automation_ide_dev" +version = "1.0.3" authors = [ { name = "JE-Chen", email = "jechenmailman@gmail.com" }, ] @@ -14,9 +14,9 @@ description = "AutomationEditor for multi automation" requires-python = ">=3.10" license-files = ["LICENSE"] dependencies = [ - "je-editor", "je_auto_control", "je_web_runner", + "je_editor_dev", "je_auto_control", "je_web_runner", "je_load_density", "je_api_testka", "je-mail-thunder", - "automation-file", "PySide6==6.10.1", "test_pioneer", "paramiko" + "automation-file", "PySide6==6.10.2", "test_pioneer", "paramiko" ] classifiers = [ "Programming Language :: Python :: 3.10", @@ -35,5 +35,6 @@ Code = "https://github.com/Intergration-Automation-Testing/AutomationEditor" file = "README.md" content-type = "text/markdown" + [tool.setuptools.packages] find = { namespaces = false } diff --git a/dev.toml b/stable.toml similarity index 80% rename from dev.toml rename to stable.toml index 0d164fd..9d6a392 100644 --- a/dev.toml +++ b/stable.toml @@ -1,12 +1,12 @@ -# Rename to dev version -# This is dev version +# Rename to build stable version +# This is stable version [build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] -name = "automation_ide_dev" -version = "0.0.67" +name = "automation_ide" +version = "1.0.3" authors = [ { name = "JE-Chen", email = "jechenmailman@gmail.com" }, ] @@ -14,9 +14,9 @@ description = "AutomationEditor for multi automation" requires-python = ">=3.10" license-files = ["LICENSE"] dependencies = [ - "je_editor_dev", "je_auto_control", "je_web_runner", + "je-editor", "je_auto_control", "je_web_runner", "je_load_density", "je_api_testka", "je-mail-thunder", - "automation-file", "PySide6==6.10.1", "test_pioneer", "paramiko" + "automation-file", "PySide6==6.10.2", "test_pioneer", "paramiko" ] classifiers = [ "Programming Language :: Python :: 3.10", @@ -35,6 +35,5 @@ Code = "https://github.com/Intergration-Automation-Testing/AutomationEditor" file = "README.md" content-type = "text/markdown" - [tool.setuptools.packages] find = { namespaces = false }