PyBreeze 1.0.28__tar.gz → 1.0.30__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pybreeze-1.0.28 → pybreeze-1.0.30}/PKG-INFO +1 -1
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend_multi_language/extend_english.py +2 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend_multi_language/extend_traditional_chinese.py +2 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/ai_gui_global_variable.py +16 -0
- pybreeze-1.0.30/pybreeze/pybreeze_ui/extend_ai_gui/code_review/code_review_thread.py +75 -0
- pybreeze-1.0.30/pybreeze/pybreeze_ui/extend_ai_gui/code_review/cot_chain.py +100 -0
- pybreeze-1.0.30/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_prompt_editor_widget.py +34 -0
- pybreeze-1.0.30/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/prompt_editor_widget.py +165 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/prompt_file_io.py +5 -0
- pybreeze-1.0.30/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_editor_widget.py +34 -0
- pybreeze-1.0.30/pybreeze/pybreeze_ui/extend_ai_gui/prompt_store.py +56 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/skills/skills_send_gui.py +24 -1
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze.egg-info/PKG-INFO +1 -1
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze.egg-info/SOURCES.txt +3 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pyproject.toml +1 -1
- pybreeze-1.0.28/pybreeze/pybreeze_ui/extend_ai_gui/code_review/code_review_thread.py +0 -113
- pybreeze-1.0.28/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_prompt_editor_widget.py +0 -145
- pybreeze-1.0.28/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_editor_widget.py +0 -145
- {pybreeze-1.0.28 → pybreeze-1.0.30}/LICENSE +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/README.md +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/__main__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/mail_thunder_extend/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/mail_thunder_extend/mail_thunder_setting.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/api_testka/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/api_testka/api_testka_process.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/auto_control/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/auto_control/auto_control_process.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/file_automation/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/file_automation/file_automation_process.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/file_runner_process.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/load_density/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/load_density/load_density_process.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/mail_thunder/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/mail_thunder/mail_thunder_process.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/process_executor_utils.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/prthinker/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/prthinker/prthinker_process.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/python_task_process_manager.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/queue_pump.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/test_pioneer/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/test_pioneer/test_pioneer_process_manager.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/web_runner/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/process_executor/web_runner/web_runner_process.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/prthinker_extend/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend/prthinker_extend/prthinker_setting.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend_multi_language/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend_multi_language/update_language_dict.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/connect_gui/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/connect_gui/ssh/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_command_widget.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_file_viewer_widget.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_host_key_policy.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_key_loader.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_login_widget.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_main_widget.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/connect_gui/url/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/connect_gui/url/ai_code_review_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/diagram_editor/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/diagram_editor/diagram_commands.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/diagram_editor/diagram_editor_widget.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/diagram_editor/diagram_items.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/diagram_editor/diagram_mermaid_parser.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/diagram_editor/diagram_net_utils.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/diagram_editor/diagram_property_panel.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/diagram_editor/diagram_scene.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/diagram_editor/diagram_view.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/dialog/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/dialog/prthinker_setting_dialog.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/editor_main/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/editor_main/file_tree_context_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/editor_main/main_ui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/code_review/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/code_review/cot_code_review_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/code_smell_detector.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_code_review.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_summary_prompt.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/global_rule.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/judge.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/judge_single_review.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/linter.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/step_by_step_analysis.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/total_summary.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_explainer.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_review.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/skills/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/jupyter_lab_gui/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/jupyter_lab_gui/jupyter_lab_thread.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/jupyter_lab_gui/jupyter_lab_widget.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/api_testka_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/api_testka_menu/build_api_testka_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/auto_control_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/auto_control_menu/build_autocontrol_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/automation_file_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/automation_file_menu/build_automation_file_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/automation_menu_factory.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/load_density_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/load_density_menu/build_load_density_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/mail_thunder_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/mail_thunder_menu/build_mail_thunder_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/prthinker_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/prthinker_menu/build_prthinker_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/test_pioneer_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/test_pioneer_menu/build_test_pioneer_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/web_runner_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/automation_menu/web_runner_menu/build_webrunner_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/build_menubar.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/extend_jeditor_tab_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/extend_jeditor_tab_menu/jupyter_lab_tab.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/install_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/install_menu/automation_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/install_menu/automation_menu/build_automation_install_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/install_menu/install_utils.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/install_menu/tools_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/install_menu/tools_menu/build_tool_install_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/menu_utils.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/plugin_menu/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/plugin_menu/build_plugin_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/plugin_menu/build_run_with_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/tools/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/menu/tools/tools_menu.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/show_code_window/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/show_code_window/code_window.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/syntax/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/syntax/syntax_extend.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/syntax/syntax_keyword.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/curl_import_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/diff_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/har_import_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/hash_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/header_analyzer_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/http_status_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/json_format_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/jwt_decoder_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/output_actions.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/query_json_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/regex_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/response_inspector_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/timestamp_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/tool_tabs.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/tools_gui/url_builder_gui.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/app_dirs.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/curl_import/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/curl_import/curl_parser.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/curl_import/request_body.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/curl_import/request_codegen.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/curl_import/script_templates.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/diff_tools/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/diff_tools/text_diff.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/exception/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/exception/exception_tags.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/exception/exceptions.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/file_process/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/file_process/get_dir_file_list.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/har_import/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/har_import/har_codegen.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/har_import/har_parser.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/hash_tools/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/hash_tools/hash_text.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/header_tools/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/header_tools/header_analyzer.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/header_tools/header_merge.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/http_reference/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/http_reference/status_codes.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/json_format/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/json_format/json_process.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/jwt_tools/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/jwt_tools/jwt_decoder.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/logging/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/logging/logger.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/manager/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/manager/package_manager/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/manager/package_manager/package_manager_class.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/network/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/network/http_client.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/network/url_validation.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/query_tools/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/query_tools/query_convert.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/regex_tools/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/regex_tools/regex_tester.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/response_inspector/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/response_inspector/response_analyzer.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/subprocess_util.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/timestamp_tools/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/timestamp_tools/timestamp_converter.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/url_tools/__init__.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/utils/url_tools/url_convert.py +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze.egg-info/dependency_links.txt +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze.egg-info/requires.txt +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze.egg-info/top_level.txt +0 -0
- {pybreeze-1.0.28 → pybreeze-1.0.30}/setup.cfg +0 -0
|
@@ -134,6 +134,8 @@ pybreeze_english_word_dict = {
|
|
|
134
134
|
"prthinker_setting_extra_arguments_label": "Extra command-line arguments",
|
|
135
135
|
"prthinker_setting_source_path_label": "prthinker source folder",
|
|
136
136
|
"prthinker_setting_stored_at_label": "Stored at:",
|
|
137
|
+
# Prompt editors — where the edited prompts override the built-in ones from
|
|
138
|
+
"prompt_editor_stored_at_label": "Prompt files (these override the built-in prompts):",
|
|
137
139
|
"prthinker_choose_source_path_label": "Choose the prthinker source folder",
|
|
138
140
|
"prthinker_need_source_path_message":
|
|
139
141
|
"prthinker is installed from source. Choose the folder holding its "
|
{pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/extend_multi_language/extend_traditional_chinese.py
RENAMED
|
@@ -134,6 +134,8 @@ pybreeze_traditional_chinese_word_dict = {
|
|
|
134
134
|
"prthinker_setting_extra_arguments_label": "額外的命令列參數",
|
|
135
135
|
"prthinker_setting_source_path_label": "prthinker 原始碼資料夾",
|
|
136
136
|
"prthinker_setting_stored_at_label": "設定檔位置:",
|
|
137
|
+
# Prompt 編輯器 —— 編輯過的 prompt 會覆寫內建版本
|
|
138
|
+
"prompt_editor_stored_at_label": "Prompt 檔案位置(會覆寫內建 prompt):",
|
|
137
139
|
"prthinker_choose_source_path_label": "選擇 prthinker 原始碼資料夾",
|
|
138
140
|
"prthinker_need_source_path_message":
|
|
139
141
|
"prthinker 是從原始碼安裝的。請選擇含有 pyproject.toml 的資料夾,"
|
{pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/ai_gui_global_variable.py
RENAMED
|
@@ -6,8 +6,14 @@ from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_t
|
|
|
6
6
|
FIRST_CODE_REVIEW_TEMPLATE
|
|
7
7
|
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.first_summary_prompt import \
|
|
8
8
|
FIRST_SUMMARY_TEMPLATE
|
|
9
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.judge import \
|
|
10
|
+
JUDGE_TEMPLATE
|
|
11
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.judge_single_review import \
|
|
12
|
+
JUDGE_SINGLE_REVIEW_TEMPLATE
|
|
9
13
|
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.linter import \
|
|
10
14
|
LINTER_TEMPLATE
|
|
15
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.step_by_step_analysis import \
|
|
16
|
+
STEP_BY_STEP_ANALYSIS_TEMPLATE
|
|
11
17
|
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.total_summary import \
|
|
12
18
|
TOTAL_SUMMARY_TEMPLATE
|
|
13
19
|
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.skills_prompt_templates.code_explainer import \
|
|
@@ -15,20 +21,30 @@ from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.skills_prompt_templates.
|
|
|
15
21
|
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.skills_prompt_templates.code_review import \
|
|
16
22
|
CODE_REVIEW_SKILL_TEMPLATE
|
|
17
23
|
|
|
24
|
+
# The order the chain runs in. Each step may only quote steps above it, so the
|
|
25
|
+
# order is a dependency order, not a preference: judge_single_review scores the
|
|
26
|
+
# review written just before it, step_by_step_analysis walks the linter and code
|
|
27
|
+
# smell findings, and judge scores the finished summary.
|
|
18
28
|
COT_TEMPLATE_FILES = [
|
|
19
29
|
"first_summary_prompt.md",
|
|
20
30
|
"first_code_review.md",
|
|
31
|
+
"judge_single_review.md",
|
|
21
32
|
"linter.md",
|
|
22
33
|
"code_smell_detector.md",
|
|
34
|
+
"step_by_step_analysis.md",
|
|
23
35
|
"total_summary.md",
|
|
36
|
+
"judge.md",
|
|
24
37
|
]
|
|
25
38
|
|
|
26
39
|
COT_TEMPLATE_RELATION = {
|
|
27
40
|
"first_summary_prompt.md": FIRST_SUMMARY_TEMPLATE,
|
|
28
41
|
"first_code_review.md": FIRST_CODE_REVIEW_TEMPLATE,
|
|
42
|
+
"judge_single_review.md": JUDGE_SINGLE_REVIEW_TEMPLATE,
|
|
29
43
|
"linter.md": LINTER_TEMPLATE,
|
|
30
44
|
"code_smell_detector.md": CODE_SMELL_DETECTOR_TEMPLATE,
|
|
45
|
+
"step_by_step_analysis.md": STEP_BY_STEP_ANALYSIS_TEMPLATE,
|
|
31
46
|
"total_summary.md": TOTAL_SUMMARY_TEMPLATE,
|
|
47
|
+
"judge.md": JUDGE_TEMPLATE,
|
|
32
48
|
}
|
|
33
49
|
|
|
34
50
|
SKILLS_TEMPLATE_FILES = [
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
# Worker Thread 負責傳送資料
|
|
4
|
+
import requests
|
|
5
|
+
from PySide6.QtCore import QThread, Signal
|
|
6
|
+
from je_editor import language_wrapper
|
|
7
|
+
|
|
8
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.code_review.cot_chain import (
|
|
9
|
+
CODE_DIFF, STEP_RESULT_KEY, build_prompt
|
|
10
|
+
)
|
|
11
|
+
from pybreeze.utils.logging.logger import pybreeze_logger
|
|
12
|
+
from pybreeze.utils.network.http_client import (
|
|
13
|
+
ResponseTooLargeError, read_capped_text, CONNECT_TIMEOUT,
|
|
14
|
+
)
|
|
15
|
+
from pybreeze.utils.network.url_validation import UnsafeURLError, validate_url
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SenderThread(QThread):
|
|
19
|
+
update_response = Signal(str, str) # (filename, response)
|
|
20
|
+
|
|
21
|
+
def __init__(self, files: list, code: str, url: str):
|
|
22
|
+
super().__init__()
|
|
23
|
+
self.files = files
|
|
24
|
+
self.code = code
|
|
25
|
+
self.url = url
|
|
26
|
+
|
|
27
|
+
def run(self):
|
|
28
|
+
try:
|
|
29
|
+
validate_url(self.url)
|
|
30
|
+
except UnsafeURLError as error:
|
|
31
|
+
pybreeze_logger.error("CoT code review URL rejected: %r", error)
|
|
32
|
+
self.update_response.emit("error", str(error))
|
|
33
|
+
return
|
|
34
|
+
# One session reuses a single TCP/TLS connection across all the
|
|
35
|
+
# sequential per-template POSTs to the same endpoint.
|
|
36
|
+
session = requests.Session()
|
|
37
|
+
try:
|
|
38
|
+
self._run_templates(session, self.code)
|
|
39
|
+
finally:
|
|
40
|
+
session.close()
|
|
41
|
+
|
|
42
|
+
def _run_templates(self, session: requests.Session, code: str) -> None:
|
|
43
|
+
# Answers accumulate here as the chain runs; a later step quotes whichever
|
|
44
|
+
# of them its template asks for. See cot_chain for the wiring.
|
|
45
|
+
results: dict[str, str] = {CODE_DIFF: code}
|
|
46
|
+
for file in self.files:
|
|
47
|
+
# Stop promptly if the widget is closing instead of firing off the
|
|
48
|
+
# remaining per-template POSTs.
|
|
49
|
+
if self.isInterruptionRequested():
|
|
50
|
+
return
|
|
51
|
+
prompt = build_prompt(file, results)
|
|
52
|
+
if prompt is None:
|
|
53
|
+
continue
|
|
54
|
+
reply_text, answered = self._ask(session, file, prompt)
|
|
55
|
+
result_key = STEP_RESULT_KEY.get(file)
|
|
56
|
+
# A failure message is shown but never stored: a later step must not
|
|
57
|
+
# quote "could not send" back to the model as if it were a review.
|
|
58
|
+
if answered and result_key is not None:
|
|
59
|
+
results[result_key] = reply_text
|
|
60
|
+
# 發送訊號更新 UI
|
|
61
|
+
self.update_response.emit(file, reply_text)
|
|
62
|
+
|
|
63
|
+
def _ask(self, session: requests.Session, file: str, prompt: str) -> tuple[str, bool]:
|
|
64
|
+
"""Send one step's prompt; return its answer and whether it arrived."""
|
|
65
|
+
try:
|
|
66
|
+
# 傳送到指定 URL(重用 session 連線)
|
|
67
|
+
resp = session.post(
|
|
68
|
+
self.url, json={"prompt": prompt},
|
|
69
|
+
timeout=(CONNECT_TIMEOUT, 60), allow_redirects=False, stream=True,
|
|
70
|
+
)
|
|
71
|
+
return read_capped_text(resp), True
|
|
72
|
+
except (requests.RequestException, ResponseTooLargeError) as error:
|
|
73
|
+
pybreeze_logger.error("CoT code review send failed for %s: %r", file, error)
|
|
74
|
+
word = language_wrapper.language_word_dict
|
|
75
|
+
return f"{word.get('cot_gui_error_sending')} {file} {error}", False
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""How a chain-of-thought review is wired: what each step quotes from the ones before it.
|
|
2
|
+
|
|
3
|
+
A step is one prompt sent to the review endpoint. Its answer is kept under a short
|
|
4
|
+
result key so a later step can quote it, and that quoting is what decides the order
|
|
5
|
+
the steps run in: a judge cannot score a review that has not been written yet, and
|
|
6
|
+
the step-by-step analysis has nothing to walk through until the linter and the code
|
|
7
|
+
smell detector have reported.
|
|
8
|
+
|
|
9
|
+
Pure logic with no Qt and no network, so the wiring can be tested on its own.
|
|
10
|
+
"""
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from collections.abc import Mapping
|
|
14
|
+
|
|
15
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.ai_gui_global_variable import COT_TEMPLATE_RELATION
|
|
16
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.cot_code_review_prompt_templates.global_rule import (
|
|
17
|
+
build_global_rule_template
|
|
18
|
+
)
|
|
19
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_store import load_prompt
|
|
20
|
+
from pybreeze.utils.logging.logger import pybreeze_logger
|
|
21
|
+
|
|
22
|
+
# The key the code under review is seeded into the results under.
|
|
23
|
+
CODE_DIFF = "code_diff"
|
|
24
|
+
|
|
25
|
+
# The result key each step's answer is stored under.
|
|
26
|
+
STEP_RESULT_KEY: dict[str, str] = {
|
|
27
|
+
"first_summary_prompt.md": "first_summary",
|
|
28
|
+
"first_code_review.md": "first_code_review",
|
|
29
|
+
"judge_single_review.md": "judge_single_review",
|
|
30
|
+
"linter.md": "linter",
|
|
31
|
+
"code_smell_detector.md": "code_smell",
|
|
32
|
+
"step_by_step_analysis.md": "step_by_step",
|
|
33
|
+
"total_summary.md": "total_summary",
|
|
34
|
+
"judge.md": "judge",
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# Each step's template placeholders, and the result key that fills each one.
|
|
38
|
+
STEP_ARGUMENTS: dict[str, dict[str, str]] = {
|
|
39
|
+
"first_summary_prompt.md": {"code_diff": CODE_DIFF},
|
|
40
|
+
"first_code_review.md": {"code_diff": CODE_DIFF},
|
|
41
|
+
# Scores the one review just written, against the code it was written about.
|
|
42
|
+
"judge_single_review.md": {
|
|
43
|
+
"review_comment": "first_code_review",
|
|
44
|
+
"code_diff": CODE_DIFF,
|
|
45
|
+
},
|
|
46
|
+
"linter.md": {"code_diff": CODE_DIFF},
|
|
47
|
+
"code_smell_detector.md": {"code_diff": CODE_DIFF},
|
|
48
|
+
# Walks every lint message and code smell through cause, impact and fix.
|
|
49
|
+
"step_by_step_analysis.md": {
|
|
50
|
+
"linter_result": "linter",
|
|
51
|
+
"code_smell_result": "code_smell",
|
|
52
|
+
},
|
|
53
|
+
"total_summary.md": {
|
|
54
|
+
"first_code_review": "first_code_review",
|
|
55
|
+
"first_summary": "first_summary",
|
|
56
|
+
"linter_result": "linter",
|
|
57
|
+
"code_smell_result": "code_smell",
|
|
58
|
+
"code_diff": CODE_DIFF,
|
|
59
|
+
},
|
|
60
|
+
# Scores the finished summary with the findings it was meant to cover in hand.
|
|
61
|
+
"judge.md": {
|
|
62
|
+
"review_comment": "total_summary",
|
|
63
|
+
"code_smell_detector_messages": "code_smell",
|
|
64
|
+
"linter_messages": "linter",
|
|
65
|
+
"code_diff": CODE_DIFF,
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def build_prompt(step: str, results: Mapping[str, str]) -> str | None:
|
|
71
|
+
"""Return the prompt for *step*, wrapped in the global review rules.
|
|
72
|
+
|
|
73
|
+
:param step: the template file name the step is known by
|
|
74
|
+
:param results: the answers collected so far, keyed as in
|
|
75
|
+
:data:`STEP_RESULT_KEY`, with the code under review under
|
|
76
|
+
:data:`CODE_DIFF`
|
|
77
|
+
:return: the prompt to send, or ``None`` when *step* is not part of the chain
|
|
78
|
+
"""
|
|
79
|
+
built_in = COT_TEMPLATE_RELATION.get(step)
|
|
80
|
+
arguments = STEP_ARGUMENTS.get(step)
|
|
81
|
+
if built_in is None or arguments is None:
|
|
82
|
+
return None
|
|
83
|
+
# A step whose input never ran quotes an empty section rather than the word
|
|
84
|
+
# "None": the model should see that there is nothing there, not read a value.
|
|
85
|
+
filled = {
|
|
86
|
+
placeholder: results.get(key, "")
|
|
87
|
+
for placeholder, key in arguments.items()
|
|
88
|
+
}
|
|
89
|
+
template = load_prompt(step, built_in)
|
|
90
|
+
try:
|
|
91
|
+
body = template.format(**filled)
|
|
92
|
+
except (KeyError, IndexError, ValueError) as error:
|
|
93
|
+
# An edited prompt that names a placeholder the chain cannot fill would
|
|
94
|
+
# otherwise take the whole review down. Fall back to the built-in and say
|
|
95
|
+
# so, rather than failing a step the user cannot debug from the UI.
|
|
96
|
+
pybreeze_logger.error(
|
|
97
|
+
"Edited prompt %s could not be filled in (%r); using the built-in",
|
|
98
|
+
step, error)
|
|
99
|
+
body = built_in.format(**filled)
|
|
100
|
+
return build_global_rule_template(prompt=body)
|
pybreeze-1.0.30/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_prompt_editor_widget.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""The editor for the chain-of-thought review prompts."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.ai_gui_global_variable import (
|
|
5
|
+
COT_TEMPLATE_FILES, COT_TEMPLATE_RELATION
|
|
6
|
+
)
|
|
7
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.prompt_editor_widget import (
|
|
8
|
+
PromptEditorLabels, PromptEditorWidget
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
COT_LABELS = PromptEditorLabels(
|
|
12
|
+
window_title="cot_prompt_editor_window_title",
|
|
13
|
+
edit_group="cot_prompt_editor_groupbox_edit_file_content",
|
|
14
|
+
create_button="cot_prompt_editor_button_create_file",
|
|
15
|
+
save_button="cot_prompt_editor_button_save_file",
|
|
16
|
+
reload_button="cot_prompt_editor_button_reload_file",
|
|
17
|
+
file_not_exist="cot_prompt_editor_file_not_exist",
|
|
18
|
+
info_title="cot_prompt_editor_msgbox_info_title",
|
|
19
|
+
error_title="cot_prompt_editor_msgbox_error_title",
|
|
20
|
+
success_title="cot_prompt_editor_msgbox_success_title",
|
|
21
|
+
file_exists="cot_prompt_editor_msgbox_file_exists",
|
|
22
|
+
file_created="cot_prompt_editor_msgbox_file_created",
|
|
23
|
+
file_saved="cot_prompt_editor_msgbox_file_saved",
|
|
24
|
+
no_file_selected="cot_prompt_editor_msgbox_no_file_selected",
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class CoTPromptEditor(PromptEditorWidget):
|
|
29
|
+
"""Edit the prompts the chain-of-thought review sends, step by step."""
|
|
30
|
+
|
|
31
|
+
def __init__(self, prompt_files=None, parent=None) -> None:
|
|
32
|
+
super().__init__(
|
|
33
|
+
prompt_files or COT_TEMPLATE_FILES, COT_TEMPLATE_RELATION,
|
|
34
|
+
COT_LABELS, parent)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""One prompt editor, shared by the CoT and the Skill template editors.
|
|
2
|
+
|
|
3
|
+
The two differ in exactly two things: which templates they list, and which
|
|
4
|
+
language keys label them. Everything else — loading the selected file, creating
|
|
5
|
+
it from its built-in template, saving, and picking up an external edit — was
|
|
6
|
+
written twice, line for line. It lives here once instead.
|
|
7
|
+
|
|
8
|
+
The language keys arrive as a :class:`PromptEditorLabels` of literal strings
|
|
9
|
+
rather than being built from a prefix, so a key that does not exist can still be
|
|
10
|
+
caught by a test reading the source rather than only at runtime.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from PySide6.QtCore import QFileSystemWatcher
|
|
18
|
+
from PySide6.QtWidgets import (
|
|
19
|
+
QComboBox, QGroupBox, QHBoxLayout, QLabel, QMessageBox, QPushButton,
|
|
20
|
+
QTextEdit, QVBoxLayout, QWidget
|
|
21
|
+
)
|
|
22
|
+
from je_editor import language_wrapper
|
|
23
|
+
|
|
24
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.prompt_file_io import save_prompt_text
|
|
25
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_store import prompt_dir, prompt_path
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass(frozen=True)
|
|
29
|
+
class PromptEditorLabels:
|
|
30
|
+
"""The language keys one editor labels itself with."""
|
|
31
|
+
|
|
32
|
+
window_title: str
|
|
33
|
+
edit_group: str
|
|
34
|
+
create_button: str
|
|
35
|
+
save_button: str
|
|
36
|
+
reload_button: str
|
|
37
|
+
file_not_exist: str
|
|
38
|
+
info_title: str
|
|
39
|
+
error_title: str
|
|
40
|
+
success_title: str
|
|
41
|
+
file_exists: str
|
|
42
|
+
file_created: str
|
|
43
|
+
file_saved: str
|
|
44
|
+
no_file_selected: str
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class PromptEditorWidget(QWidget):
|
|
48
|
+
"""Edit the prompt files that override the built-in templates."""
|
|
49
|
+
|
|
50
|
+
def __init__(self, files: list[str], templates: dict[str, str],
|
|
51
|
+
labels: PromptEditorLabels, parent=None) -> None:
|
|
52
|
+
"""
|
|
53
|
+
:param files: the template file names this editor offers, in order
|
|
54
|
+
:param templates: file name -> the template compiled into the source tree
|
|
55
|
+
:param labels: the language keys this editor is labelled with
|
|
56
|
+
"""
|
|
57
|
+
super().__init__(parent)
|
|
58
|
+
self.prompt_files = files
|
|
59
|
+
self.templates = templates
|
|
60
|
+
self._labels = labels
|
|
61
|
+
self.current_file: str | None = None
|
|
62
|
+
|
|
63
|
+
word = language_wrapper.language_word_dict
|
|
64
|
+
self.setWindowTitle(word.get(labels.window_title))
|
|
65
|
+
|
|
66
|
+
self.file_selector = QComboBox()
|
|
67
|
+
self.file_selector.addItems(self.prompt_files)
|
|
68
|
+
self.file_selector.currentIndexChanged.connect(self.load_file_content)
|
|
69
|
+
|
|
70
|
+
self.middle_editor = QTextEdit()
|
|
71
|
+
group = QGroupBox(word.get(labels.edit_group))
|
|
72
|
+
group_layout = QVBoxLayout()
|
|
73
|
+
group_layout.addWidget(self.middle_editor)
|
|
74
|
+
group.setLayout(group_layout)
|
|
75
|
+
|
|
76
|
+
self.reload_button = QPushButton(word.get(labels.reload_button))
|
|
77
|
+
self.reload_button.clicked.connect(
|
|
78
|
+
lambda: self.load_file_content(self.file_selector.currentIndex()))
|
|
79
|
+
self.save_button = QPushButton(word.get(labels.save_button))
|
|
80
|
+
self.save_button.clicked.connect(self.save_file)
|
|
81
|
+
self.create_button = QPushButton(word.get(labels.create_button))
|
|
82
|
+
self.create_button.clicked.connect(self.create_file)
|
|
83
|
+
|
|
84
|
+
bottom_layout = QHBoxLayout()
|
|
85
|
+
bottom_layout.addWidget(self.file_selector)
|
|
86
|
+
bottom_layout.addStretch()
|
|
87
|
+
for button in (self.reload_button, self.save_button, self.create_button):
|
|
88
|
+
bottom_layout.addWidget(button)
|
|
89
|
+
|
|
90
|
+
# 這些檔案覆寫實際送出的 prompt,位置要讓人找得到
|
|
91
|
+
# These files override the prompt that is sent, so say where they are
|
|
92
|
+
where = QLabel(f"{word.get('prompt_editor_stored_at_label')} {prompt_dir()}")
|
|
93
|
+
where.setWordWrap(True)
|
|
94
|
+
|
|
95
|
+
main_layout = QVBoxLayout(self)
|
|
96
|
+
main_layout.addWidget(group)
|
|
97
|
+
main_layout.addWidget(where)
|
|
98
|
+
main_layout.addLayout(bottom_layout)
|
|
99
|
+
|
|
100
|
+
# 檔案監控器:外部改動即時反映 / Pick up edits made outside the editor
|
|
101
|
+
self.watcher = QFileSystemWatcher(
|
|
102
|
+
[str(prompt_path(name)) for name in self.prompt_files])
|
|
103
|
+
self.watcher.fileChanged.connect(self.on_file_changed)
|
|
104
|
+
|
|
105
|
+
if self.prompt_files:
|
|
106
|
+
self.load_file_content(0)
|
|
107
|
+
|
|
108
|
+
def load_file_content(self, index: int) -> None:
|
|
109
|
+
"""載入選擇的檔案內容 / Show the selected file, or say it is not there yet."""
|
|
110
|
+
name = self.prompt_files[index]
|
|
111
|
+
self.current_file = str(prompt_path(name))
|
|
112
|
+
path = Path(self.current_file)
|
|
113
|
+
if path.is_file():
|
|
114
|
+
self.middle_editor.setPlainText(path.read_text(encoding="utf-8"))
|
|
115
|
+
return
|
|
116
|
+
self.middle_editor.setPlainText(
|
|
117
|
+
language_wrapper.language_word_dict.get(
|
|
118
|
+
self._labels.file_not_exist).format(filename=name))
|
|
119
|
+
|
|
120
|
+
def create_file(self) -> None:
|
|
121
|
+
"""用內建模板建立目前選擇的檔案 / Create the selected file from its built-in template."""
|
|
122
|
+
word = language_wrapper.language_word_dict
|
|
123
|
+
if self.current_file is None:
|
|
124
|
+
return
|
|
125
|
+
if Path(self.current_file).is_file():
|
|
126
|
+
QMessageBox.information(
|
|
127
|
+
self, word.get(self._labels.info_title),
|
|
128
|
+
word.get(self._labels.file_exists).format(filename=self.current_file))
|
|
129
|
+
return
|
|
130
|
+
|
|
131
|
+
content = self.templates.get(Path(self.current_file).name, "")
|
|
132
|
+
if not save_prompt_text(
|
|
133
|
+
self, self.current_file, content, word.get(self._labels.error_title)):
|
|
134
|
+
return
|
|
135
|
+
|
|
136
|
+
# Only now does the file exist, so only now can it be watched for the
|
|
137
|
+
# external edits this editor promises to pick up.
|
|
138
|
+
self.watcher.addPath(self.current_file)
|
|
139
|
+
QMessageBox.information(
|
|
140
|
+
self, word.get(self._labels.success_title),
|
|
141
|
+
word.get(self._labels.file_created).format(filename=self.current_file))
|
|
142
|
+
self.load_file_content(self.file_selector.currentIndex())
|
|
143
|
+
|
|
144
|
+
def on_file_changed(self, path: str) -> None:
|
|
145
|
+
"""外部改動時重新載入 / Reload when the file changes underneath us."""
|
|
146
|
+
if path == self.current_file:
|
|
147
|
+
self.load_file_content(self.file_selector.currentIndex())
|
|
148
|
+
|
|
149
|
+
def save_file(self) -> None:
|
|
150
|
+
"""把編輯區內容存回檔案 / Write the edit area back to the file."""
|
|
151
|
+
word = language_wrapper.language_word_dict
|
|
152
|
+
if self.current_file is None:
|
|
153
|
+
QMessageBox.warning(
|
|
154
|
+
self, word.get(self._labels.error_title),
|
|
155
|
+
word.get(self._labels.no_file_selected))
|
|
156
|
+
return
|
|
157
|
+
|
|
158
|
+
if not save_prompt_text(
|
|
159
|
+
self, self.current_file, self.middle_editor.toPlainText(),
|
|
160
|
+
word.get(self._labels.error_title)):
|
|
161
|
+
return
|
|
162
|
+
self.watcher.addPath(self.current_file)
|
|
163
|
+
QMessageBox.information(
|
|
164
|
+
self, word.get(self._labels.success_title),
|
|
165
|
+
word.get(self._labels.file_saved).format(filename=self.current_file))
|
|
@@ -6,6 +6,8 @@ a user-facing dialog instead of an uncaught traceback.
|
|
|
6
6
|
"""
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
9
11
|
from PySide6.QtWidgets import QMessageBox, QWidget
|
|
10
12
|
|
|
11
13
|
from pybreeze.utils.logging.logger import pybreeze_logger
|
|
@@ -18,6 +20,9 @@ def save_prompt_text(parent: QWidget, path: str, content: str, error_title: str)
|
|
|
18
20
|
caller can skip its success message).
|
|
19
21
|
"""
|
|
20
22
|
try:
|
|
23
|
+
# The directory is made here rather than on every read, so a session that
|
|
24
|
+
# only looks at the built-in prompts leaves nothing behind.
|
|
25
|
+
Path(path).parent.mkdir(parents=True, exist_ok=True)
|
|
21
26
|
with open(path, "w", encoding="utf-8") as file_handle:
|
|
22
27
|
file_handle.write(content)
|
|
23
28
|
return True
|
pybreeze-1.0.30/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_editor_widget.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""The editor for the reusable skill prompts."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.ai_gui_global_variable import (
|
|
5
|
+
SKILLS_TEMPLATE_FILES, SKILLS_TEMPLATE_RELATION
|
|
6
|
+
)
|
|
7
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_edit_gui.prompt_editor_widget import (
|
|
8
|
+
PromptEditorLabels, PromptEditorWidget
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
SKILL_LABELS = PromptEditorLabels(
|
|
12
|
+
window_title="skill_prompt_editor_window_title",
|
|
13
|
+
edit_group="skill_prompt_editor_groupbox_edit_file_content",
|
|
14
|
+
create_button="skill_prompt_editor_button_create_file",
|
|
15
|
+
save_button="skill_prompt_editor_button_save_file",
|
|
16
|
+
reload_button="skill_prompt_editor_button_reload_file",
|
|
17
|
+
file_not_exist="skill_prompt_editor_file_not_exist",
|
|
18
|
+
info_title="skill_prompt_editor_msgbox_info_title",
|
|
19
|
+
error_title="skill_prompt_editor_msgbox_error_title",
|
|
20
|
+
success_title="skill_prompt_editor_msgbox_success_title",
|
|
21
|
+
file_exists="skill_prompt_editor_msgbox_file_exists",
|
|
22
|
+
file_created="skill_prompt_editor_msgbox_file_created",
|
|
23
|
+
file_saved="skill_prompt_editor_msgbox_file_saved",
|
|
24
|
+
no_file_selected="skill_prompt_editor_msgbox_no_file_selected",
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SkillPromptEditor(PromptEditorWidget):
|
|
29
|
+
"""Edit the reusable skill prompts the send window offers."""
|
|
30
|
+
|
|
31
|
+
def __init__(self, skill_files=None, parent=None) -> None:
|
|
32
|
+
super().__init__(
|
|
33
|
+
skill_files or SKILLS_TEMPLATE_FILES, SKILLS_TEMPLATE_RELATION,
|
|
34
|
+
SKILL_LABELS, parent)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Where the editable prompt templates live, and how one is resolved.
|
|
2
|
+
|
|
3
|
+
Every template ships as a constant in the source tree and may be overridden by a
|
|
4
|
+
file the user edits. The file wins when it has content, so editing a prompt in the
|
|
5
|
+
editor changes what the review actually sends — which is the only reason the
|
|
6
|
+
editor is there.
|
|
7
|
+
|
|
8
|
+
The files sit under the user's own directory rather than the working one, so the
|
|
9
|
+
prompts someone has written are the same whichever folder the IDE was started
|
|
10
|
+
from, matching where the SSH known hosts and the prthinker settings are kept.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from pybreeze.utils.app_dirs import pybreeze_data_dir
|
|
17
|
+
from pybreeze.utils.logging.logger import pybreeze_logger
|
|
18
|
+
|
|
19
|
+
_PROMPT_DIR_NAME = "prompts"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def prompt_dir() -> Path:
|
|
23
|
+
"""Return the directory the editable prompt files live in.
|
|
24
|
+
|
|
25
|
+
Reading and naming a prompt must not create anything: opening the editor to
|
|
26
|
+
look at a built-in prompt should leave no directory behind. ``save_prompt_text``
|
|
27
|
+
makes the directory when there is finally something to put in it.
|
|
28
|
+
"""
|
|
29
|
+
return pybreeze_data_dir() / _PROMPT_DIR_NAME
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def prompt_path(name: str) -> Path:
|
|
33
|
+
"""Return the file the prompt called *name* is edited in."""
|
|
34
|
+
return prompt_dir() / name
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def load_prompt(name: str, default: str) -> str:
|
|
38
|
+
"""Return the edited prompt *name*, or the built-in *default*.
|
|
39
|
+
|
|
40
|
+
A file that is missing, empty or unreadable falls back to the built-in: an
|
|
41
|
+
override that says nothing must not leave a review step with nothing to ask,
|
|
42
|
+
and a file that cannot be read must not stop the review.
|
|
43
|
+
|
|
44
|
+
:param name: the prompt's file name, e.g. ``linter.md``
|
|
45
|
+
:param default: the template compiled into the source tree
|
|
46
|
+
:return: the prompt text to use
|
|
47
|
+
"""
|
|
48
|
+
path = prompt_path(name)
|
|
49
|
+
if not path.is_file():
|
|
50
|
+
return default
|
|
51
|
+
try:
|
|
52
|
+
edited = path.read_text(encoding="utf-8")
|
|
53
|
+
except OSError as error:
|
|
54
|
+
pybreeze_logger.error("Prompt %s could not be read: %r", name, error)
|
|
55
|
+
return default
|
|
56
|
+
return edited if edited.strip() else default
|
{pybreeze-1.0.28 → pybreeze-1.0.30}/pybreeze/pybreeze_ui/extend_ai_gui/skills/skills_send_gui.py
RENAMED
|
@@ -8,7 +8,10 @@ from PySide6.QtWidgets import (
|
|
|
8
8
|
from PySide6.QtCore import QThread, Signal
|
|
9
9
|
from je_editor import language_wrapper
|
|
10
10
|
|
|
11
|
-
from pybreeze.pybreeze_ui.extend_ai_gui.ai_gui_global_variable import
|
|
11
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.ai_gui_global_variable import (
|
|
12
|
+
SKILLS_TEMPLATE_FILES, SKILLS_TEMPLATE_RELATION
|
|
13
|
+
)
|
|
14
|
+
from pybreeze.pybreeze_ui.extend_ai_gui.prompt_store import load_prompt
|
|
12
15
|
from pybreeze.utils.logging.logger import pybreeze_logger
|
|
13
16
|
from pybreeze.utils.network.http_client import (
|
|
14
17
|
ResponseTooLargeError, read_capped_text, CONNECT_TIMEOUT, truncate_for_display,
|
|
@@ -80,6 +83,7 @@ class SkillsSendGUI(QWidget):
|
|
|
80
83
|
self.prompt_select_label = QLabel(language_wrapper.language_word_dict.get("skills_prompt_select_label"))
|
|
81
84
|
self.prompt_select = QComboBox()
|
|
82
85
|
self.prompt_select.addItems(SKILLS_TEMPLATE_FILES)
|
|
86
|
+
self.prompt_select.currentTextChanged.connect(self.load_selected_prompt)
|
|
83
87
|
layout.addWidget(self.prompt_select_label)
|
|
84
88
|
layout.addWidget(self.prompt_select)
|
|
85
89
|
|
|
@@ -104,6 +108,25 @@ class SkillsSendGUI(QWidget):
|
|
|
104
108
|
self.setLayout(layout)
|
|
105
109
|
|
|
106
110
|
self.thread = None # 保存執行緒
|
|
111
|
+
# 開啟時就把選到的那個模板載進來,選單才不是擺著好看
|
|
112
|
+
# Load the selected template on open, so the selector does something
|
|
113
|
+
self.load_selected_prompt(self.prompt_select.currentText())
|
|
114
|
+
|
|
115
|
+
def load_selected_prompt(self, name: str) -> None:
|
|
116
|
+
"""
|
|
117
|
+
把選到的 skill 模板載進編輯區
|
|
118
|
+
Put the selected skill template in the edit area.
|
|
119
|
+
|
|
120
|
+
以編輯過的檔案為準,沒有就用內建的;載進來以後仍然可以改,送出的是編輯區的內容。
|
|
121
|
+
The edited file wins over the built-in one. What lands here stays
|
|
122
|
+
editable: what is sent is whatever the edit area holds.
|
|
123
|
+
|
|
124
|
+
:param name: 模板檔名 / the template's file name
|
|
125
|
+
"""
|
|
126
|
+
built_in = SKILLS_TEMPLATE_RELATION.get(name)
|
|
127
|
+
if built_in is None:
|
|
128
|
+
return
|
|
129
|
+
self.prompt_input.setPlainText(load_prompt(name, built_in))
|
|
107
130
|
|
|
108
131
|
def send_prompt(self):
|
|
109
132
|
# Ignore re-submits while a request is in flight: reassigning self.thread
|
|
@@ -66,11 +66,14 @@ pybreeze/pybreeze_ui/editor_main/file_tree_context_menu.py
|
|
|
66
66
|
pybreeze/pybreeze_ui/editor_main/main_ui.py
|
|
67
67
|
pybreeze/pybreeze_ui/extend_ai_gui/__init__.py
|
|
68
68
|
pybreeze/pybreeze_ui/extend_ai_gui/ai_gui_global_variable.py
|
|
69
|
+
pybreeze/pybreeze_ui/extend_ai_gui/prompt_store.py
|
|
69
70
|
pybreeze/pybreeze_ui/extend_ai_gui/code_review/__init__.py
|
|
70
71
|
pybreeze/pybreeze_ui/extend_ai_gui/code_review/code_review_thread.py
|
|
72
|
+
pybreeze/pybreeze_ui/extend_ai_gui/code_review/cot_chain.py
|
|
71
73
|
pybreeze/pybreeze_ui/extend_ai_gui/code_review/cot_code_review_gui.py
|
|
72
74
|
pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/__init__.py
|
|
73
75
|
pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_prompt_editor_widget.py
|
|
76
|
+
pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/prompt_editor_widget.py
|
|
74
77
|
pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/prompt_file_io.py
|
|
75
78
|
pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_editor_widget.py
|
|
76
79
|
pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/__init__.py
|