PyBreeze-dev 1.0.16__tar.gz → 1.0.18__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.
Files changed (271) hide show
  1. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/PKG-INFO +71 -6
  2. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/README.md +69 -4
  3. pybreeze_dev-1.0.18/pybreeze/extend/language_server/__init__.py +6 -0
  4. pybreeze_dev-1.0.18/pybreeze/extend/language_server/__main__.py +17 -0
  5. pybreeze_dev-1.0.18/pybreeze/extend/language_server/launch.py +42 -0
  6. pybreeze_dev-1.0.18/pybreeze/extend/language_server/server_main.py +59 -0
  7. pybreeze_dev-1.0.18/pybreeze/extend_multi_language/english_integrations.py +165 -0
  8. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend_multi_language/extend_english.py +76 -49
  9. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend_multi_language/extend_traditional_chinese.py +75 -87
  10. pybreeze_dev-1.0.18/pybreeze/extend_multi_language/supported_languages.py +88 -0
  11. pybreeze_dev-1.0.18/pybreeze/extend_multi_language/traditional_chinese_error_text.py +115 -0
  12. pybreeze_dev-1.0.18/pybreeze/extend_multi_language/traditional_chinese_integrations.py +162 -0
  13. pybreeze_dev-1.0.18/pybreeze/extend_multi_language/update_language_dict.py +36 -0
  14. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/design/flow_layout.py +101 -0
  15. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/design/panels.py +78 -0
  16. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/design/tokens.py +117 -0
  17. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/diagram_editor/diagram_editor_widget.py +14 -15
  18. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/editor_main/main_ui.py +52 -1
  19. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/prompt_editor_widget.py +12 -7
  20. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/mcp_gui/mcp_client_gui.py +411 -0
  21. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/mcp_gui/mcp_panels.py +290 -0
  22. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/mcp_gui/mcp_profile_dialog.py +176 -0
  23. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/mcp_gui/mcp_server_panel.py +175 -0
  24. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/mcp_gui/mcp_worker.py +41 -0
  25. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/tools/tools_menu.py +271 -0
  26. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/navigation/navigation_dock.py +128 -0
  27. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/navigation/navigation_model.py +151 -0
  28. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/report_gui/report_viewer_gui.py +394 -0
  29. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/thread_keeper.py +30 -0
  30. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/curl_import_gui.py +24 -12
  31. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/har_import_gui.py +27 -10
  32. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/header_analyzer_gui.py +43 -3
  33. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/tools_gui/import_gaps.py +48 -0
  34. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/tools_gui/json_editor_gui.py +398 -0
  35. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/tools_gui/json_tree_panel.py +338 -0
  36. pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/tools_gui/keyword_reference_gui.py +272 -0
  37. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/response_inspector_gui.py +5 -6
  38. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/curl_import/script_templates.py +1 -33
  39. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/exception/exception_tags.py +39 -0
  40. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/exception/exceptions.py +16 -0
  41. pybreeze_dev-1.0.18/pybreeze/utils/execution_report/html_report.py +125 -0
  42. pybreeze_dev-1.0.18/pybreeze/utils/execution_report/junit_xml.py +176 -0
  43. pybreeze_dev-1.0.18/pybreeze/utils/execution_report/record_reports.py +208 -0
  44. pybreeze_dev-1.0.18/pybreeze/utils/execution_report/report_files.py +165 -0
  45. pybreeze_dev-1.0.18/pybreeze/utils/execution_report/report_filter.py +106 -0
  46. pybreeze_dev-1.0.18/pybreeze/utils/execution_report/report_schema.py +373 -0
  47. pybreeze_dev-1.0.18/pybreeze/utils/execution_report/safe_xml.py +136 -0
  48. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/har_import/har_codegen.py +7 -36
  49. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/header_tools/header_analyzer.py +32 -22
  50. pybreeze_dev-1.0.18/pybreeze/utils/header_tools/header_rules.py +179 -0
  51. pybreeze_dev-1.0.18/pybreeze/utils/header_tools/header_sarif.py +191 -0
  52. pybreeze_dev-1.0.18/pybreeze/utils/import_targets/builtin_targets.py +69 -0
  53. pybreeze_dev-1.0.18/pybreeze/utils/import_targets/normalized_request.py +119 -0
  54. pybreeze_dev-1.0.18/pybreeze/utils/import_targets/target_registry.py +156 -0
  55. pybreeze_dev-1.0.18/pybreeze/utils/import_targets/webrunner_target.py +79 -0
  56. pybreeze_dev-1.0.18/pybreeze/utils/json_format/json_document.py +262 -0
  57. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/json_format/json_process.py +6 -6
  58. pybreeze_dev-1.0.18/pybreeze/utils/json_format/json_tree_edit.py +300 -0
  59. pybreeze_dev-1.0.18/pybreeze/utils/language_service/action_adapter.py +343 -0
  60. pybreeze_dev-1.0.18/pybreeze/utils/language_service/framework_profiles.py +55 -0
  61. pybreeze_dev-1.0.18/pybreeze/utils/language_service/json_scan.py +274 -0
  62. pybreeze_dev-1.0.18/pybreeze/utils/language_service/keyword_metadata.py +223 -0
  63. pybreeze_dev-1.0.18/pybreeze/utils/language_service/lsp_server.py +431 -0
  64. pybreeze_dev-1.0.18/pybreeze/utils/language_service/metadata_probe.py +163 -0
  65. pybreeze_dev-1.0.18/pybreeze/utils/language_service/service_adapter.py +271 -0
  66. pybreeze_dev-1.0.18/pybreeze/utils/manager/package_manager/__init__.py +0 -0
  67. pybreeze_dev-1.0.18/pybreeze/utils/mcp/__init__.py +0 -0
  68. pybreeze_dev-1.0.18/pybreeze/utils/mcp/mcp_call_log.py +113 -0
  69. pybreeze_dev-1.0.18/pybreeze/utils/mcp/mcp_client.py +414 -0
  70. pybreeze_dev-1.0.18/pybreeze/utils/mcp/mcp_profile.py +184 -0
  71. pybreeze_dev-1.0.18/pybreeze/utils/mcp/mcp_redaction.py +76 -0
  72. pybreeze_dev-1.0.18/pybreeze/utils/mcp/mcp_transport.py +155 -0
  73. pybreeze_dev-1.0.18/pybreeze/utils/network/__init__.py +0 -0
  74. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/network/url_validation.py +1 -1
  75. pybreeze_dev-1.0.18/pybreeze/utils/query_tools/__init__.py +0 -0
  76. pybreeze_dev-1.0.18/pybreeze/utils/regex_tools/__init__.py +0 -0
  77. pybreeze_dev-1.0.18/pybreeze/utils/response_inspector/__init__.py +0 -0
  78. pybreeze_dev-1.0.18/pybreeze/utils/timestamp_tools/__init__.py +0 -0
  79. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/timestamp_tools/timestamp_converter.py +73 -11
  80. pybreeze_dev-1.0.18/pybreeze/utils/ui_state.py +48 -0
  81. pybreeze_dev-1.0.18/pybreeze/utils/url_tools/__init__.py +0 -0
  82. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze_dev.egg-info/PKG-INFO +71 -6
  83. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze_dev.egg-info/SOURCES.txt +59 -0
  84. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze_dev.egg-info/requires.txt +1 -1
  85. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pyproject.toml +2 -2
  86. pybreeze_dev-1.0.16/pybreeze/extend_multi_language/update_language_dict.py +0 -29
  87. pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/tools/tools_menu.py +0 -298
  88. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/LICENSE +0 -0
  89. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/__init__.py +0 -0
  90. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/__main__.py +0 -0
  91. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/__init__.py +0 -0
  92. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/mail_thunder_extend/__init__.py +0 -0
  93. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/mail_thunder_extend/mail_thunder_setting.py +0 -0
  94. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/process_executor/__init__.py +0 -0
  95. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/process_executor/file_runner_process.py +0 -0
  96. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/process_executor/process_executor_utils.py +0 -0
  97. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/process_executor/prthinker/__init__.py +0 -0
  98. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/process_executor/prthinker/prthinker_process.py +0 -0
  99. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/process_executor/python_task_process_manager.py +0 -0
  100. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/process_executor/queue_pump.py +0 -0
  101. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/process_executor/run_notice.py +0 -0
  102. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/process_executor/test_pioneer/__init__.py +0 -0
  103. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/process_executor/test_pioneer/test_pioneer_process_manager.py +0 -0
  104. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/prthinker_extend/__init__.py +0 -0
  105. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend/prthinker_extend/prthinker_setting.py +0 -0
  106. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/extend_multi_language/__init__.py +0 -0
  107. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/__init__.py +0 -0
  108. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/busy_cursor.py +0 -0
  109. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/closing.py +0 -0
  110. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/code_result_logs.py +0 -0
  111. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/connect_gui/__init__.py +0 -0
  112. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/connect_gui/ssh/__init__.py +0 -0
  113. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/connect_gui/ssh/sftp_session.py +0 -0
  114. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_command_widget.py +0 -0
  115. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_connect_thread.py +0 -0
  116. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_file_viewer_widget.py +0 -0
  117. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_host_key_policy.py +0 -0
  118. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_key_loader.py +0 -0
  119. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_login_widget.py +0 -0
  120. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/connect_gui/ssh/ssh_main_widget.py +0 -0
  121. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/connect_gui/url/__init__.py +0 -0
  122. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/connect_gui/url/ai_code_review_gui.py +0 -0
  123. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/diagram_editor → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/design}/__init__.py +0 -0
  124. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/dialog → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/diagram_editor}/__init__.py +0 -0
  125. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/diagram_editor/diagram_commands.py +0 -0
  126. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/diagram_editor/diagram_items.py +0 -0
  127. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/diagram_editor/diagram_mermaid_parser.py +0 -0
  128. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/diagram_editor/diagram_net_utils.py +0 -0
  129. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/diagram_editor/diagram_property_panel.py +0 -0
  130. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/diagram_editor/diagram_scene.py +0 -0
  131. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/diagram_editor/diagram_view.py +0 -0
  132. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/editor_main → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/dialog}/__init__.py +0 -0
  133. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/dialog/prthinker_setting_dialog.py +0 -0
  134. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/extend_ai_gui → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/editor_main}/__init__.py +0 -0
  135. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/editor_main/file_tree_context_menu.py +0 -0
  136. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/editor_main/pybreeze_icon.ico +0 -0
  137. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/error_text.py +0 -0
  138. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/exact_text.py +0 -0
  139. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/extend_ai_gui/code_review → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/extend_ai_gui}/__init__.py +0 -0
  140. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/ai_gui_global_variable.py +0 -0
  141. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/extend_ai_gui/code_review}/__init__.py +0 -0
  142. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/code_review/code_review_thread.py +0 -0
  143. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/code_review/cot_chain.py +0 -0
  144. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/code_review/cot_code_review_gui.py +0 -0
  145. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui}/__init__.py +0 -0
  146. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates}/__init__.py +0 -0
  147. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/code_smell_detector.py +0 -0
  148. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_code_review.py +0 -0
  149. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/first_summary_prompt.py +0 -0
  150. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/global_rule.py +0 -0
  151. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/judge.py +0 -0
  152. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/judge_single_review.py +0 -0
  153. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/linter.py +0 -0
  154. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/step_by_step_analysis.py +0 -0
  155. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_code_review_prompt_templates/total_summary.py +0 -0
  156. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/cot_prompt_editor_widget.py +0 -0
  157. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/prompt_file_io.py +0 -0
  158. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_editor_widget.py +0 -0
  159. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/extend_ai_gui/skills → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates}/__init__.py +0 -0
  160. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_explainer.py +0 -0
  161. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_edit_gui/skills_prompt_templates/code_review.py +0 -0
  162. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/prompt_store.py +0 -0
  163. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/jupyter_lab_gui → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/extend_ai_gui/skills}/__init__.py +0 -0
  164. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/extend_ai_gui/skills/skills_send_gui.py +0 -0
  165. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/fixed_pitch.py +0 -0
  166. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/gui_thread_gc.py +0 -0
  167. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/jupyter_lab_gui}/__init__.py +0 -0
  168. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/jupyter_lab_gui/jupyter_lab_thread.py +0 -0
  169. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/jupyter_lab_gui/jupyter_lab_widget.py +0 -0
  170. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/jupyter_lab_gui/lab_page.py +0 -0
  171. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/automation_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/mcp_gui}/__init__.py +0 -0
  172. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/automation_menu/api_testka_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu}/__init__.py +0 -0
  173. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/automation_menu/auto_control_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/automation_menu}/__init__.py +0 -0
  174. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/automation_menu/automation_file_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/automation_menu/api_testka_menu}/__init__.py +0 -0
  175. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/automation_menu/api_testka_menu/build_api_testka_menu.py +0 -0
  176. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/automation_menu/load_density_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/automation_menu/auto_control_menu}/__init__.py +0 -0
  177. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/automation_menu/auto_control_menu/build_autocontrol_menu.py +0 -0
  178. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/automation_menu/mail_thunder_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/automation_menu/automation_file_menu}/__init__.py +0 -0
  179. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/automation_menu/automation_file_menu/build_automation_file_menu.py +0 -0
  180. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/automation_menu/automation_menu_factory.py +0 -0
  181. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/automation_menu/prthinker_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/automation_menu/load_density_menu}/__init__.py +0 -0
  182. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/automation_menu/load_density_menu/build_load_density_menu.py +0 -0
  183. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/automation_menu/test_pioneer_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/automation_menu/mail_thunder_menu}/__init__.py +0 -0
  184. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/automation_menu/mail_thunder_menu/build_mail_thunder_menu.py +0 -0
  185. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/automation_menu/web_runner_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/automation_menu/prthinker_menu}/__init__.py +0 -0
  186. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/automation_menu/prthinker_menu/build_prthinker_menu.py +0 -0
  187. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/extend_jeditor_tab_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/automation_menu/test_pioneer_menu}/__init__.py +0 -0
  188. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/automation_menu/test_pioneer_menu/build_test_pioneer_menu.py +0 -0
  189. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/install_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/automation_menu/web_runner_menu}/__init__.py +0 -0
  190. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/automation_menu/web_runner_menu/build_webrunner_menu.py +0 -0
  191. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/build_menubar.py +0 -0
  192. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/install_menu/automation_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/extend_jeditor_tab_menu}/__init__.py +0 -0
  193. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/extend_jeditor_tab_menu/jupyter_lab_tab.py +0 -0
  194. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/install_menu/tools_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/install_menu}/__init__.py +0 -0
  195. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/plugin_menu → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/install_menu/automation_menu}/__init__.py +0 -0
  196. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/install_menu/automation_menu/build_automation_install_menu.py +0 -0
  197. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/install_menu/install_utils.py +0 -0
  198. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/menu/tools → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/install_menu/tools_menu}/__init__.py +0 -0
  199. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/install_menu/tools_menu/build_tool_install_menu.py +0 -0
  200. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/menu_utils.py +0 -0
  201. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/show_code_window → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/plugin_menu}/__init__.py +0 -0
  202. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/plugin_menu/build_plugin_menu.py +0 -0
  203. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/menu/plugin_menu/build_run_with_menu.py +0 -0
  204. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/syntax → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/menu/tools}/__init__.py +0 -0
  205. {pybreeze_dev-1.0.16/pybreeze/pybreeze_ui/tools_gui → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/navigation}/__init__.py +0 -0
  206. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/plain_text.py +0 -0
  207. {pybreeze_dev-1.0.16/pybreeze/utils → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/report_gui}/__init__.py +0 -0
  208. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/run_shortcut.py +0 -0
  209. {pybreeze_dev-1.0.16/pybreeze/utils/curl_import → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/show_code_window}/__init__.py +0 -0
  210. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/show_code_window/code_window.py +0 -0
  211. {pybreeze_dev-1.0.16/pybreeze/utils/diff_tools → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/syntax}/__init__.py +0 -0
  212. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/syntax/syntax_extend.py +0 -0
  213. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/syntax/syntax_keyword.py +0 -0
  214. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/terminal_view.py +0 -0
  215. {pybreeze_dev-1.0.16/pybreeze/utils/exception → pybreeze_dev-1.0.18/pybreeze/pybreeze_ui/tools_gui}/__init__.py +0 -0
  216. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/diff_gui.py +0 -0
  217. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/hash_gui.py +0 -0
  218. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/http_status_gui.py +0 -0
  219. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/json_format_gui.py +0 -0
  220. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/jwt_decoder_gui.py +0 -0
  221. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/output_actions.py +0 -0
  222. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/query_json_gui.py +0 -0
  223. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/regex_gui.py +0 -0
  224. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/timestamp_gui.py +0 -0
  225. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/tool_tabs.py +0 -0
  226. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/pybreeze_ui/tools_gui/url_builder_gui.py +0 -0
  227. {pybreeze_dev-1.0.16/pybreeze/utils/file_process → pybreeze_dev-1.0.18/pybreeze/utils}/__init__.py +0 -0
  228. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/app_dirs.py +0 -0
  229. {pybreeze_dev-1.0.16/pybreeze/utils/har_import → pybreeze_dev-1.0.18/pybreeze/utils/curl_import}/__init__.py +0 -0
  230. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/curl_import/curl_parser.py +0 -0
  231. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/curl_import/request_body.py +0 -0
  232. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/curl_import/request_codegen.py +0 -0
  233. {pybreeze_dev-1.0.16/pybreeze/utils/hash_tools → pybreeze_dev-1.0.18/pybreeze/utils/diff_tools}/__init__.py +0 -0
  234. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/diff_tools/text_diff.py +0 -0
  235. {pybreeze_dev-1.0.16/pybreeze/utils/header_tools → pybreeze_dev-1.0.18/pybreeze/utils/exception}/__init__.py +0 -0
  236. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/exception/error_templates.py +0 -0
  237. {pybreeze_dev-1.0.16/pybreeze/utils/http_reference → pybreeze_dev-1.0.18/pybreeze/utils/execution_report}/__init__.py +0 -0
  238. {pybreeze_dev-1.0.16/pybreeze/utils/jwt_tools → pybreeze_dev-1.0.18/pybreeze/utils/file_process}/__init__.py +0 -0
  239. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/file_process/get_dir_file_list.py +0 -0
  240. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/file_process/read_capped.py +0 -0
  241. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/file_process/replace_file.py +0 -0
  242. {pybreeze_dev-1.0.16/pybreeze/utils/logging → pybreeze_dev-1.0.18/pybreeze/utils/har_import}/__init__.py +0 -0
  243. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/har_import/har_parser.py +0 -0
  244. {pybreeze_dev-1.0.16/pybreeze/utils/manager → pybreeze_dev-1.0.18/pybreeze/utils/hash_tools}/__init__.py +0 -0
  245. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/hash_tools/hash_text.py +0 -0
  246. {pybreeze_dev-1.0.16/pybreeze/utils/manager/package_manager → pybreeze_dev-1.0.18/pybreeze/utils/header_tools}/__init__.py +0 -0
  247. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/header_tools/header_merge.py +0 -0
  248. {pybreeze_dev-1.0.16/pybreeze/utils/network → pybreeze_dev-1.0.18/pybreeze/utils/http_reference}/__init__.py +0 -0
  249. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/http_reference/status_codes.py +0 -0
  250. {pybreeze_dev-1.0.16/pybreeze/utils/query_tools → pybreeze_dev-1.0.18/pybreeze/utils/import_targets}/__init__.py +0 -0
  251. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/json_format/__init__.py +0 -0
  252. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/json_format/view_safe.py +0 -0
  253. {pybreeze_dev-1.0.16/pybreeze/utils/regex_tools → pybreeze_dev-1.0.18/pybreeze/utils/jwt_tools}/__init__.py +0 -0
  254. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/jwt_tools/jwt_decoder.py +0 -0
  255. {pybreeze_dev-1.0.16/pybreeze/utils/response_inspector → pybreeze_dev-1.0.18/pybreeze/utils/language_service}/__init__.py +0 -0
  256. {pybreeze_dev-1.0.16/pybreeze/utils/timestamp_tools → pybreeze_dev-1.0.18/pybreeze/utils/logging}/__init__.py +0 -0
  257. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/logging/logger.py +0 -0
  258. {pybreeze_dev-1.0.16/pybreeze/utils/url_tools → pybreeze_dev-1.0.18/pybreeze/utils/manager}/__init__.py +0 -0
  259. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/manager/package_manager/package_manager_class.py +0 -0
  260. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/network/http_client.py +0 -0
  261. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/network/public_http.py +0 -0
  262. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/query_tools/query_convert.py +0 -0
  263. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/regex_tools/regex_tester.py +0 -0
  264. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/response_inspector/response_analyzer.py +0 -0
  265. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/subprocess_util.py +0 -0
  266. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/terminal_style.py +0 -0
  267. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/terminal_text.py +0 -0
  268. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze/utils/url_tools/url_convert.py +0 -0
  269. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze_dev.egg-info/dependency_links.txt +0 -0
  270. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/pybreeze_dev.egg-info/top_level.txt +0 -0
  271. {pybreeze_dev-1.0.16 → pybreeze_dev-1.0.18}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pybreeze_dev
3
- Version: 1.0.16
3
+ Version: 1.0.18
4
4
  Summary: IDE for multi automation
5
5
  Author-email: JE-Chen <jechenmailman@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/Integration-Automation/PyBreeze
@@ -24,7 +24,7 @@ Requires-Dist: je_web_runner
24
24
  Requires-Dist: je_load_density
25
25
  Requires-Dist: je_api_testka
26
26
  Requires-Dist: je-mail-thunder
27
- Requires-Dist: automation-file
27
+ Requires-Dist: automation-file[all]
28
28
  Requires-Dist: PySide6==6.11.2
29
29
  Requires-Dist: test_pioneer
30
30
  Requires-Dist: paramiko
@@ -107,6 +107,8 @@ Each module gets the same menu shape: **Run** (single script, batch directory, w
107
107
 
108
108
  - **Automation keyword sets** — the `AT_*` / GUI / Web / Load keyword sets are registered for `.json`, and TestPioneer's schema for `.yml` and `.yaml`, on top of JEditor's language support. JEditor does not colour them yet: it highlights those files with its own rules for the suffix, which leave registered keywords out
109
109
  - **Code editor** — built on [JEditor](https://github.com/Integration-Automation/JEDITOR): tabs, project tree, format checker, debugger, terminal and a git client pane
110
+ - **Navigation panel** — a dock at the left lists what the menus hold as one tree (Automation, Tools, Settings): type in its box to find a tool or a command by name, then press Enter or double-click to open it. **Dock ▸ Navigation** shows and hides it, and a panel closed on purpose stays closed at the next start
111
+ - **Fits a small screen** — a tool tab never asks for more than 60 font heights of width: a row of buttons too long for the tab wraps onto the next line instead of pushing the window wider than the display
110
112
  - **Script execution** — single or batch, each run in a window of its own with a Stop button (Run ▸ Stop All Program stops them all), which asks whether to stop the run when it is closed while the run goes on; action files are passed by path, and a script from the tab in front that is too long for a Windows command line (~32 KB) goes through a temporary file
111
113
  - **Report generation** — HTML / JSON / XML after a run, with optional email delivery
112
114
  - **Integrated JupyterLab** — launches as a tab, in the same interpreter a run would use, installing JupyterLab there if it is missing, and upgrading it and its server first when either is a release with a known vulnerability (JupyterLab before 4.5.10 or 4.6.0–4.6.1, jupyter_server before 2.20.0); the tab stays on the lab, and a link to anywhere else opens in your browser
@@ -126,7 +128,7 @@ Paste a `curl` command from your browser's dev tools and pick a target. The pars
126
128
  |---|---|
127
129
  | ![cURL import to pytest](images/tool_curl_import.png) | ![cURL import to APITestka action](images/tool_curl_import_action.png) |
128
130
 
129
- Targets: Python `requests`, a ready-to-run **pytest** test, **APITestka** (Python or a `[["AT_test_api_method", {...}]]` action list that `execute_files` runs directly), and a **LoadDensity** Locust load test. Copy the output, open it straight into an editor tab, or save it with the right extension. One click also hands the parsed URL to the URL parser/builder or the headers to the header analyzer.
131
+ Targets: Python `requests`, a ready-to-run **pytest** test, **APITestka** (Python or a `[["AT_test_api_method", {...}]]` action list that `execute_files` runs directly), a **LoadDensity** Locust load test, and a **WebRunner** action list that visits the address in a browser. A target that cannot send everything a request holds says so under the output ("Not sent by this target: headers · the body"): a LoadDensity run drives a method and a URL, and a browser visit keeps the URL, the cookies and a time limit. Copy the output, open it straight into an editor tab, or save it with the right extension. One click also hands the parsed URL to the URL parser/builder or the headers to the header analyzer.
130
132
 
131
133
  ### HAR Import — a whole session becomes a test suite
132
134
 
@@ -148,12 +150,73 @@ The status code is looked up in the HTTP reference, headers are parsed, a JSON b
148
150
 
149
151
  Reports names sent more than once, `Set-Cookie` entries missing `Secure` / `HttpOnly` / `SameSite` and those a browser drops outright (a `__Secure-` / `__Host-` name whose rules are broken, `SameSite=None` without `Secure`), wildcard CORS (and the wildcard-plus-credentials combination browsers reject outright), an HSTS `max-age` too short to survive a restart, CSP `unsafe-inline` / `unsafe-eval`, product banners, headers current browsers ignore (`X-XSS-Protection` other than `0`, `Expect-CT`, `Public-Key-Pins`, `P3P`, the old prefixed CSP names), and — for responses — the security headers that are absent, counting a CSP `frame-ancestors` directive as `X-Frame-Options`, as the OWASP HTTP Headers Cheat Sheet does. Headers carrying credentials are reported **by name only**; their values never enter the report.
150
152
 
153
+ **Export findings as SARIF** saves the analysis as a SARIF 2.1.0 file that GitHub Code Scanning and other security tooling read: each finding with its rule, level, line, what to do about it and a link. The same export runs without the IDE, for CI:
154
+
155
+ ```bash
156
+ python -m pybreeze.utils.header_tools.header_sarif response-headers.txt -o headers.sarif
157
+ ```
158
+
159
+ `-` reads the headers from standard input, leaving out `-o` writes to standard output, and `--fail-on-warning` exits with 1 when a finding is a warning. The report names rules and lines and quotes no header value.
160
+
151
161
  ### Text Diff
152
162
 
153
163
  ![Text Diff](images/tool_diff.png)
154
164
 
155
165
  Compare two payloads — an expected vs. actual API response, say — and get a unified diff, its added and removed lines in the theme's colours, plus a one-line added/removed summary.
156
166
 
167
+ ### Report Viewer
168
+
169
+ **Tools → Report Viewer Tab** opens what a run produced, whatever ran it, into one view.
170
+
171
+ - **Reads** the automation packages' own reports (APITestka, AutoControl, WebRunner, LoadDensity: the `<name>_success.json` / `<name>_failure.json` pair or the `.xml` pair; open either and the other is read with it), **JUnit XML** (pytest's `--junitxml`, and most other runners), and reports exported from PyBreeze. What a file is, is told from what it holds.
172
+ - **Shows** each run as a tree with how every result ended and how long it took; the selected result's details and error, its output, what it left behind, and the package's own record of it, untouched.
173
+ - **Filters** all open runs together: by ending (passed, failed, error, skipped), by time taken, by package, and by text in a name or an error. A line under the tree counts what is shown.
174
+ - **Exports** a run as an execution report (JSON), as **JUnit XML** for a CI service's test summary, or as one self-contained **HTML page** for people, which can be opened here again.
175
+ - The **MCP Client**'s Calls page opens its session here with **Open in Report Viewer**.
176
+
177
+ A report is a file from somewhere: it is read as data (XML that declares a document type is refused), everything in it is shown as text, and the paths it names are listed, not opened.
178
+
179
+ ### MCP Client
180
+
181
+ **Tools → MCP Client Tab** connects to [Model Context Protocol](https://modelcontextprotocol.io) servers and shows what each offers: **tools** to call, **resources** to read, **prompts** to fill in.
182
+
183
+ - **Servers** are set up once and kept for you (`~/.pybreeze/mcp_servers.json`, readable by you alone): a name, the command that starts the server (one argument a line, never a shell line), its environment variables, and how long a request may take. The file uses the `mcpServers` layout other clients write, so a list made elsewhere can be dropped in.
184
+ - **A call is asked about first**: the tool, the server and the arguments as they will be sent, with No as the default. Tick *Do not ask again* to trust one tool of one server. What a server says of its own tool ("changes nothing") is shown, not relied on.
185
+ - **A server that comes with a project** (`.mcp.json` in the project folder) is listed, never started by itself: connecting to it shows its command and asks.
186
+ - **Cancel** gives up a call on its way; a server that does not answer within its time limit is given up on; one that goes away is said so, with the last line of its own log. **Connect** again to start over.
187
+ - **Calls** lists the session: when, which tool, how it ended, how long it took. **Export Session...** saves it as an execution report (JSON).
188
+
189
+ Put keys and tokens in the server's environment variables, not in its command: their values are shown as dots, and are taken out of the log, of error messages and of exported sessions wherever they turn up. Servers are started as local programs (the protocol's standard-input-and-output transport).
190
+
191
+ ### Keywords for action scripts
192
+
193
+ A WebRunner, AutoControl or LoadDensity script is a JSON list of actions, `["keyword"]` or `["keyword", arguments]`. Open one (`.json`) in the editor and it is completed and checked against the keywords of the framework **as it is installed**:
194
+
195
+ - **Completion** — the framework's keywords where an action's name goes, a keyword's parameters where an argument's name goes.
196
+ - **Diagnostics** — a keyword that version does not have (with the nearest one suggested), a parameter the keyword does not take, a required one left out, a list of values of the wrong length, an action of the wrong shape, and text that is not JSON. In the IDE's language.
197
+ - **Hover** and **go to definition** — a keyword's signature and documentation, and the line of the package that defines it.
198
+
199
+ Nothing about a keyword is kept in PyBreeze. Each framework is asked, in a process of its own, by the interpreter that runs your scripts (the one chosen in the IDE, a `.venv` in the project, else the IDE's own), so upgrading a framework changes what is offered. A framework that is missing or fails to import costs its own keywords and nothing else.
200
+
201
+ **Tools → Automation Keywords Tab** shows the same keywords: each framework's version, what the editor offers for it, every keyword with its parameters and documentation, a filter, and **Copy as Action**. When a framework gives none, it says why.
202
+
203
+ The editor gets all this from a language server, which any editor that speaks the Language Server Protocol can start too:
204
+
205
+ ```bash
206
+ python -m pybreeze.extend.language_server [--interpreter /path/to/python] [--language Traditional_Chinese]
207
+ ```
208
+
209
+ ### JSON Editor
210
+
211
+ Edit a JSON file as a **Tree** or as **Text** (**Tools → JSON Editor Tab**). Both are views of one document, so they cannot disagree.
212
+
213
+ - **Tree** — add, delete, move up or down, and rename in place; type over a value, or give it another type (object, array, string, number, boolean, null). A number is kept as it is written: `1.0` stays `1.0`.
214
+ - **Text** — the JSON itself, always there. It is checked as you type and a line under the views says where it stops being JSON; the tree waits until it is JSON again, and nothing typed is thrown away.
215
+ - **Undo / Redo** step through the document whichever view changed it, and a tab with unsaved changes asks before it closes or opens another file.
216
+ - A file is written back the way it was found: its indent (spaces or tabs), on one line if it was, with its final line break. Alignment by hand and blank lines are not kept by an edit in the tree.
217
+
218
+ It is a JSON editor, not a second code editor: a file is opened into it from its **Open...** button.
219
+
157
220
  ### The everyday utilities
158
221
 
159
222
  Each is a tab or a dock, each has the same copy / open-in-editor / save-to-file row along the bottom.
@@ -167,7 +230,7 @@ Each is a tab or a dock, each has the same copy / open-in-editor / save-to-file
167
230
 
168
231
  ![Timestamp converter, hash generator, query/JSON, URL builder](images/tools_montage_b.png)
169
232
 
170
- - **Timestamp Converter** — a Unix epoch (seconds, milliseconds, microseconds or nanoseconds, auto-detected) or an ISO-8601 date-time (with `Z`, `+08`, `+0800` or `+08:00`, any number of fraction digits, basic or extended) in, every representation out in UTC. Deterministic and independent of the local time zone.
233
+ - **Timestamp Converter** — a Unix epoch (seconds, milliseconds, microseconds or nanoseconds, auto-detected) or an ISO-8601 date-time (with `Z`, `+08`, `+0800` or `+08:00`, any number of fraction digits, basic or extended, and an RFC 9557 zone after the offset as Java's `ZonedDateTime` writes it: `+01:00[Europe/Paris]`) or an HTTP date (`Sun, 06 Nov 1994 08:49:37 GMT`, as in `Date` or `Last-Modified`, and the two older forms RFC 9110 accepts) in, every representation out in UTC. Deterministic and independent of the local time zone.
171
234
  - **Hash Generator** — SHA-256, SHA-512, SHA-1 and MD5 at once (MD5/SHA-1 for interoperability with `usedforsecurity=False`, never for security decisions).
172
235
  - **Query ⇄ JSON** — `application/x-www-form-urlencoded` to pretty JSON and back; repeated keys become arrays and vice versa.
173
236
  - **URL Parser / Builder** — scheme, host, port, path, query, fragment and credentials as an editable JSON object, and back again. Brackets IPv6 literals and re-encodes query parameters for you.
@@ -248,7 +311,7 @@ Loaded plugins appear under their own **Plugins** menu with an About entry and o
248
311
  - **English** (default)
249
312
  - **Traditional Chinese** (繁體中文)
250
313
 
251
- Menus, dialogs, the reasons a tool refuses its input and the run window's own notices (`[Error] …`, `[Run] …`) all follow the chosen language. Both dictionaries carry the same 768 keys, and a test enforces that parity so a new string can never land in one language only. The Language menu also lists JEditor's Japanese and Simplified Chinese: picked, JEditor's own menus change and PyBreeze's strings stay in English. Further languages can be added via translation plugins.
314
+ Menus, dialogs, the reasons a tool refuses its input and the run window's own notices (`[Error] …`, `[Run] …`) all follow the chosen language. Both dictionaries carry the same 995 keys, and a test enforces that parity so a new string can never land in one language only. English and Traditional Chinese are the languages PyBreeze maintains. The Language menu also lists JEditor's Japanese (日本語) and Simplified Chinese (简体中文), which PyBreeze passes on without translating: picked, JEditor's own menus change and PyBreeze's strings stay in English. Further languages can be added via translation plugins.
252
315
 
253
316
  ---
254
317
 
@@ -377,6 +440,8 @@ Once launched:
377
440
  4. **Generate** an HTML / JSON / XML report
378
441
  5. **Send** it by email through the MailThunder integration
379
442
 
443
+ New here? The [tutorials](https://pybreeze.readthedocs.io/en/latest/Eng/tutorials/index.html) are thirteen short pages, each with an example that runs and what to expect from it: the first launch, a first API, browser, desktop and load run, tests from cURL and HAR, header findings as SARIF in CI, the JSON editor, keywords for action scripts, the MCP client, reports in CI, plugins, and troubleshooting. They test a small site on your own machine, so none of them needs an account.
444
+
380
445
  ### Log file
381
446
 
382
447
  PyBreeze writes its log to `~/.pybreeze/logs/PyBreeze.log`: UTF-8, appended to by every run, each line carrying the process ID. Only warnings and errors also appear in the editor's Code Result panel. Two environment variables change this:
@@ -482,7 +547,7 @@ python -m pytest test/test_utils/ -v --tb=short
482
547
 
483
548
  - **Unit tests** — `test/test_utils/`, covering the pure-logic layer (curl and HAR parsing, header analysis, SSRF validation, JWT, hashing, timestamps, diffing) plus headless Qt widget tests via `QT_QPA_PLATFORM=offscreen`, with Hypothesis property tests over the parsers. The SSH terminal and the SFTP file tree also log in to an SSH server the tests start on the loopback address, which serves a temporary folder over SFTP
484
549
  - **Startup tests** — `test/unit_test/start_automation/` launches the IDE in debug mode and verifies it comes up and exits cleanly
485
- - **CI** — GitHub Actions on Windows across Python 3.10 – 3.14, on every push and PR plus a nightly run; a push to `dev` that passes also publishes `pybreeze_dev` when the package changed
550
+ - **CI** — GitHub Actions: the whole suite on Windows across Python 3.10 – 3.14, and a short set of platform smoke tests on Linux and macOS, on every push and PR plus a nightly run; a push to `dev` that passes the suite also publishes `pybreeze_dev` when the package changed
486
551
  - **Static analysis** — SonarCloud, Codacy and Bandit
487
552
 
488
553
  ---
@@ -74,6 +74,8 @@ Each module gets the same menu shape: **Run** (single script, batch directory, w
74
74
 
75
75
  - **Automation keyword sets** — the `AT_*` / GUI / Web / Load keyword sets are registered for `.json`, and TestPioneer's schema for `.yml` and `.yaml`, on top of JEditor's language support. JEditor does not colour them yet: it highlights those files with its own rules for the suffix, which leave registered keywords out
76
76
  - **Code editor** — built on [JEditor](https://github.com/Integration-Automation/JEDITOR): tabs, project tree, format checker, debugger, terminal and a git client pane
77
+ - **Navigation panel** — a dock at the left lists what the menus hold as one tree (Automation, Tools, Settings): type in its box to find a tool or a command by name, then press Enter or double-click to open it. **Dock ▸ Navigation** shows and hides it, and a panel closed on purpose stays closed at the next start
78
+ - **Fits a small screen** — a tool tab never asks for more than 60 font heights of width: a row of buttons too long for the tab wraps onto the next line instead of pushing the window wider than the display
77
79
  - **Script execution** — single or batch, each run in a window of its own with a Stop button (Run ▸ Stop All Program stops them all), which asks whether to stop the run when it is closed while the run goes on; action files are passed by path, and a script from the tab in front that is too long for a Windows command line (~32 KB) goes through a temporary file
78
80
  - **Report generation** — HTML / JSON / XML after a run, with optional email delivery
79
81
  - **Integrated JupyterLab** — launches as a tab, in the same interpreter a run would use, installing JupyterLab there if it is missing, and upgrading it and its server first when either is a release with a known vulnerability (JupyterLab before 4.5.10 or 4.6.0–4.6.1, jupyter_server before 2.20.0); the tab stays on the lab, and a link to anywhere else opens in your browser
@@ -93,7 +95,7 @@ Paste a `curl` command from your browser's dev tools and pick a target. The pars
93
95
  |---|---|
94
96
  | ![cURL import to pytest](images/tool_curl_import.png) | ![cURL import to APITestka action](images/tool_curl_import_action.png) |
95
97
 
96
- Targets: Python `requests`, a ready-to-run **pytest** test, **APITestka** (Python or a `[["AT_test_api_method", {...}]]` action list that `execute_files` runs directly), and a **LoadDensity** Locust load test. Copy the output, open it straight into an editor tab, or save it with the right extension. One click also hands the parsed URL to the URL parser/builder or the headers to the header analyzer.
98
+ Targets: Python `requests`, a ready-to-run **pytest** test, **APITestka** (Python or a `[["AT_test_api_method", {...}]]` action list that `execute_files` runs directly), a **LoadDensity** Locust load test, and a **WebRunner** action list that visits the address in a browser. A target that cannot send everything a request holds says so under the output ("Not sent by this target: headers · the body"): a LoadDensity run drives a method and a URL, and a browser visit keeps the URL, the cookies and a time limit. Copy the output, open it straight into an editor tab, or save it with the right extension. One click also hands the parsed URL to the URL parser/builder or the headers to the header analyzer.
97
99
 
98
100
  ### HAR Import — a whole session becomes a test suite
99
101
 
@@ -115,12 +117,73 @@ The status code is looked up in the HTTP reference, headers are parsed, a JSON b
115
117
 
116
118
  Reports names sent more than once, `Set-Cookie` entries missing `Secure` / `HttpOnly` / `SameSite` and those a browser drops outright (a `__Secure-` / `__Host-` name whose rules are broken, `SameSite=None` without `Secure`), wildcard CORS (and the wildcard-plus-credentials combination browsers reject outright), an HSTS `max-age` too short to survive a restart, CSP `unsafe-inline` / `unsafe-eval`, product banners, headers current browsers ignore (`X-XSS-Protection` other than `0`, `Expect-CT`, `Public-Key-Pins`, `P3P`, the old prefixed CSP names), and — for responses — the security headers that are absent, counting a CSP `frame-ancestors` directive as `X-Frame-Options`, as the OWASP HTTP Headers Cheat Sheet does. Headers carrying credentials are reported **by name only**; their values never enter the report.
117
119
 
120
+ **Export findings as SARIF** saves the analysis as a SARIF 2.1.0 file that GitHub Code Scanning and other security tooling read: each finding with its rule, level, line, what to do about it and a link. The same export runs without the IDE, for CI:
121
+
122
+ ```bash
123
+ python -m pybreeze.utils.header_tools.header_sarif response-headers.txt -o headers.sarif
124
+ ```
125
+
126
+ `-` reads the headers from standard input, leaving out `-o` writes to standard output, and `--fail-on-warning` exits with 1 when a finding is a warning. The report names rules and lines and quotes no header value.
127
+
118
128
  ### Text Diff
119
129
 
120
130
  ![Text Diff](images/tool_diff.png)
121
131
 
122
132
  Compare two payloads — an expected vs. actual API response, say — and get a unified diff, its added and removed lines in the theme's colours, plus a one-line added/removed summary.
123
133
 
134
+ ### Report Viewer
135
+
136
+ **Tools → Report Viewer Tab** opens what a run produced, whatever ran it, into one view.
137
+
138
+ - **Reads** the automation packages' own reports (APITestka, AutoControl, WebRunner, LoadDensity: the `<name>_success.json` / `<name>_failure.json` pair or the `.xml` pair; open either and the other is read with it), **JUnit XML** (pytest's `--junitxml`, and most other runners), and reports exported from PyBreeze. What a file is, is told from what it holds.
139
+ - **Shows** each run as a tree with how every result ended and how long it took; the selected result's details and error, its output, what it left behind, and the package's own record of it, untouched.
140
+ - **Filters** all open runs together: by ending (passed, failed, error, skipped), by time taken, by package, and by text in a name or an error. A line under the tree counts what is shown.
141
+ - **Exports** a run as an execution report (JSON), as **JUnit XML** for a CI service's test summary, or as one self-contained **HTML page** for people, which can be opened here again.
142
+ - The **MCP Client**'s Calls page opens its session here with **Open in Report Viewer**.
143
+
144
+ A report is a file from somewhere: it is read as data (XML that declares a document type is refused), everything in it is shown as text, and the paths it names are listed, not opened.
145
+
146
+ ### MCP Client
147
+
148
+ **Tools → MCP Client Tab** connects to [Model Context Protocol](https://modelcontextprotocol.io) servers and shows what each offers: **tools** to call, **resources** to read, **prompts** to fill in.
149
+
150
+ - **Servers** are set up once and kept for you (`~/.pybreeze/mcp_servers.json`, readable by you alone): a name, the command that starts the server (one argument a line, never a shell line), its environment variables, and how long a request may take. The file uses the `mcpServers` layout other clients write, so a list made elsewhere can be dropped in.
151
+ - **A call is asked about first**: the tool, the server and the arguments as they will be sent, with No as the default. Tick *Do not ask again* to trust one tool of one server. What a server says of its own tool ("changes nothing") is shown, not relied on.
152
+ - **A server that comes with a project** (`.mcp.json` in the project folder) is listed, never started by itself: connecting to it shows its command and asks.
153
+ - **Cancel** gives up a call on its way; a server that does not answer within its time limit is given up on; one that goes away is said so, with the last line of its own log. **Connect** again to start over.
154
+ - **Calls** lists the session: when, which tool, how it ended, how long it took. **Export Session...** saves it as an execution report (JSON).
155
+
156
+ Put keys and tokens in the server's environment variables, not in its command: their values are shown as dots, and are taken out of the log, of error messages and of exported sessions wherever they turn up. Servers are started as local programs (the protocol's standard-input-and-output transport).
157
+
158
+ ### Keywords for action scripts
159
+
160
+ A WebRunner, AutoControl or LoadDensity script is a JSON list of actions, `["keyword"]` or `["keyword", arguments]`. Open one (`.json`) in the editor and it is completed and checked against the keywords of the framework **as it is installed**:
161
+
162
+ - **Completion** — the framework's keywords where an action's name goes, a keyword's parameters where an argument's name goes.
163
+ - **Diagnostics** — a keyword that version does not have (with the nearest one suggested), a parameter the keyword does not take, a required one left out, a list of values of the wrong length, an action of the wrong shape, and text that is not JSON. In the IDE's language.
164
+ - **Hover** and **go to definition** — a keyword's signature and documentation, and the line of the package that defines it.
165
+
166
+ Nothing about a keyword is kept in PyBreeze. Each framework is asked, in a process of its own, by the interpreter that runs your scripts (the one chosen in the IDE, a `.venv` in the project, else the IDE's own), so upgrading a framework changes what is offered. A framework that is missing or fails to import costs its own keywords and nothing else.
167
+
168
+ **Tools → Automation Keywords Tab** shows the same keywords: each framework's version, what the editor offers for it, every keyword with its parameters and documentation, a filter, and **Copy as Action**. When a framework gives none, it says why.
169
+
170
+ The editor gets all this from a language server, which any editor that speaks the Language Server Protocol can start too:
171
+
172
+ ```bash
173
+ python -m pybreeze.extend.language_server [--interpreter /path/to/python] [--language Traditional_Chinese]
174
+ ```
175
+
176
+ ### JSON Editor
177
+
178
+ Edit a JSON file as a **Tree** or as **Text** (**Tools → JSON Editor Tab**). Both are views of one document, so they cannot disagree.
179
+
180
+ - **Tree** — add, delete, move up or down, and rename in place; type over a value, or give it another type (object, array, string, number, boolean, null). A number is kept as it is written: `1.0` stays `1.0`.
181
+ - **Text** — the JSON itself, always there. It is checked as you type and a line under the views says where it stops being JSON; the tree waits until it is JSON again, and nothing typed is thrown away.
182
+ - **Undo / Redo** step through the document whichever view changed it, and a tab with unsaved changes asks before it closes or opens another file.
183
+ - A file is written back the way it was found: its indent (spaces or tabs), on one line if it was, with its final line break. Alignment by hand and blank lines are not kept by an edit in the tree.
184
+
185
+ It is a JSON editor, not a second code editor: a file is opened into it from its **Open...** button.
186
+
124
187
  ### The everyday utilities
125
188
 
126
189
  Each is a tab or a dock, each has the same copy / open-in-editor / save-to-file row along the bottom.
@@ -134,7 +197,7 @@ Each is a tab or a dock, each has the same copy / open-in-editor / save-to-file
134
197
 
135
198
  ![Timestamp converter, hash generator, query/JSON, URL builder](images/tools_montage_b.png)
136
199
 
137
- - **Timestamp Converter** — a Unix epoch (seconds, milliseconds, microseconds or nanoseconds, auto-detected) or an ISO-8601 date-time (with `Z`, `+08`, `+0800` or `+08:00`, any number of fraction digits, basic or extended) in, every representation out in UTC. Deterministic and independent of the local time zone.
200
+ - **Timestamp Converter** — a Unix epoch (seconds, milliseconds, microseconds or nanoseconds, auto-detected) or an ISO-8601 date-time (with `Z`, `+08`, `+0800` or `+08:00`, any number of fraction digits, basic or extended, and an RFC 9557 zone after the offset as Java's `ZonedDateTime` writes it: `+01:00[Europe/Paris]`) or an HTTP date (`Sun, 06 Nov 1994 08:49:37 GMT`, as in `Date` or `Last-Modified`, and the two older forms RFC 9110 accepts) in, every representation out in UTC. Deterministic and independent of the local time zone.
138
201
  - **Hash Generator** — SHA-256, SHA-512, SHA-1 and MD5 at once (MD5/SHA-1 for interoperability with `usedforsecurity=False`, never for security decisions).
139
202
  - **Query ⇄ JSON** — `application/x-www-form-urlencoded` to pretty JSON and back; repeated keys become arrays and vice versa.
140
203
  - **URL Parser / Builder** — scheme, host, port, path, query, fragment and credentials as an editable JSON object, and back again. Brackets IPv6 literals and re-encodes query parameters for you.
@@ -215,7 +278,7 @@ Loaded plugins appear under their own **Plugins** menu with an About entry and o
215
278
  - **English** (default)
216
279
  - **Traditional Chinese** (繁體中文)
217
280
 
218
- Menus, dialogs, the reasons a tool refuses its input and the run window's own notices (`[Error] …`, `[Run] …`) all follow the chosen language. Both dictionaries carry the same 768 keys, and a test enforces that parity so a new string can never land in one language only. The Language menu also lists JEditor's Japanese and Simplified Chinese: picked, JEditor's own menus change and PyBreeze's strings stay in English. Further languages can be added via translation plugins.
281
+ Menus, dialogs, the reasons a tool refuses its input and the run window's own notices (`[Error] …`, `[Run] …`) all follow the chosen language. Both dictionaries carry the same 995 keys, and a test enforces that parity so a new string can never land in one language only. English and Traditional Chinese are the languages PyBreeze maintains. The Language menu also lists JEditor's Japanese (日本語) and Simplified Chinese (简体中文), which PyBreeze passes on without translating: picked, JEditor's own menus change and PyBreeze's strings stay in English. Further languages can be added via translation plugins.
219
282
 
220
283
  ---
221
284
 
@@ -344,6 +407,8 @@ Once launched:
344
407
  4. **Generate** an HTML / JSON / XML report
345
408
  5. **Send** it by email through the MailThunder integration
346
409
 
410
+ New here? The [tutorials](https://pybreeze.readthedocs.io/en/latest/Eng/tutorials/index.html) are thirteen short pages, each with an example that runs and what to expect from it: the first launch, a first API, browser, desktop and load run, tests from cURL and HAR, header findings as SARIF in CI, the JSON editor, keywords for action scripts, the MCP client, reports in CI, plugins, and troubleshooting. They test a small site on your own machine, so none of them needs an account.
411
+
347
412
  ### Log file
348
413
 
349
414
  PyBreeze writes its log to `~/.pybreeze/logs/PyBreeze.log`: UTF-8, appended to by every run, each line carrying the process ID. Only warnings and errors also appear in the editor's Code Result panel. Two environment variables change this:
@@ -449,7 +514,7 @@ python -m pytest test/test_utils/ -v --tb=short
449
514
 
450
515
  - **Unit tests** — `test/test_utils/`, covering the pure-logic layer (curl and HAR parsing, header analysis, SSRF validation, JWT, hashing, timestamps, diffing) plus headless Qt widget tests via `QT_QPA_PLATFORM=offscreen`, with Hypothesis property tests over the parsers. The SSH terminal and the SFTP file tree also log in to an SSH server the tests start on the loopback address, which serves a temporary folder over SFTP
451
516
  - **Startup tests** — `test/unit_test/start_automation/` launches the IDE in debug mode and verifies it comes up and exits cleanly
452
- - **CI** — GitHub Actions on Windows across Python 3.10 – 3.14, on every push and PR plus a nightly run; a push to `dev` that passes also publishes `pybreeze_dev` when the package changed
517
+ - **CI** — GitHub Actions: the whole suite on Windows across Python 3.10 – 3.14, and a short set of platform smoke tests on Linux and macOS, on every push and PR plus a nightly run; a push to `dev` that passes the suite also publishes `pybreeze_dev` when the package changed
453
518
  - **Static analysis** — SonarCloud, Codacy and Bandit
454
519
 
455
520
  ---
@@ -0,0 +1,6 @@
1
+ """The action language server as a process the editor starts (``python -m pybreeze.extend.language_server``).
2
+
3
+ The protocol and the answers are in ``pybreeze/utils/language_service/``. Here
4
+ is what makes a process of them: the entry point, the frameworks asked for
5
+ their keywords, and the command JEditor's editors start it with.
6
+ """
@@ -0,0 +1,17 @@
1
+ """Start the action language server on this process's standard input and output."""
2
+ from __future__ import annotations
3
+
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ # The editor starts this file by its path, not with -m: the folder the IDE is
8
+ # in (a project someone opened) is then not on the import path, and a package
9
+ # there called pybreeze is not what gets imported. Started that way the path
10
+ # begins with this folder, and the folder PyBreeze is in takes its place.
11
+ if not __package__:
12
+ sys.path[0] = str(Path(__file__).resolve().parents[3])
13
+
14
+ from pybreeze.extend.language_server.server_main import main # noqa: E402 — the import path is set first
15
+
16
+ if __name__ == "__main__":
17
+ raise SystemExit(main(sys.argv[1:]))
@@ -0,0 +1,42 @@
1
+ """Have JEditor's editors start the action language server for JSON files.
2
+
3
+ JEditor's editor asks a language server about the file it holds, chosen by the
4
+ file's suffix from ``je_editor.utils.lsp.language_servers.DEFAULT_SERVERS``.
5
+ PyBreeze puts its own server there for ``.json``: the automation scripts are
6
+ JSON, and for any other JSON file the server says only whether it is JSON.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import sys
11
+ from pathlib import Path
12
+
13
+ from je_editor.utils.lsp.language_servers import DEFAULT_SERVERS
14
+
15
+ # The files the server answers for
16
+ ACTION_SCRIPT_SUFFIX = ".json"
17
+ _ENTRY = Path(__file__).with_name("__main__.py")
18
+
19
+
20
+ def can_serve() -> bool:
21
+ """Whether there is an interpreter to run the server with: not in a packaged build, where ``sys.executable`` is the app."""
22
+ return not getattr(sys, "frozen", False)
23
+
24
+
25
+ def server_command(interpreter: str | None, language: str) -> list[str]:
26
+ """The command that starts the server.
27
+
28
+ The entry is named by its path rather than with ``-m``, which would put
29
+ the folder the IDE is in first on the server's import path.
30
+
31
+ :param interpreter: the Python that runs the scripts; the IDE's own when ``None``
32
+ :param language: the IDE's language, by JEditor's name for it
33
+ """
34
+ command = [sys.executable, str(_ENTRY), "--language", language]
35
+ if interpreter:
36
+ command += ["--interpreter", interpreter]
37
+ return command
38
+
39
+
40
+ def offer_to_jeditor(interpreter: str | None, language: str) -> None:
41
+ """Make the action language server the one JEditor's editors start for a JSON file."""
42
+ DEFAULT_SERVERS[ACTION_SCRIPT_SUFFIX] = server_command(interpreter, language)
@@ -0,0 +1,59 @@
1
+ """The action language server's process: its arguments, the frameworks it asks, the language it answers in."""
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import sys
6
+ from collections.abc import Callable
7
+ from functools import partial
8
+ from importlib import metadata as installed
9
+
10
+ from pybreeze.extend_multi_language.supported_languages import MAINTAINED
11
+ from pybreeze.utils.exception.exceptions import LanguageServiceException
12
+ from pybreeze.utils.language_service.framework_profiles import PROFILES, FrameworkProfile
13
+ from pybreeze.utils.language_service.lsp_server import ActionLanguageServer, serve
14
+ from pybreeze.utils.language_service.metadata_probe import read_metadata
15
+
16
+
17
+ def words_of(language: str) -> dict[str, str]:
18
+ """PyBreeze's strings in *language*; in English for a language PyBreeze does not maintain."""
19
+ return next((each.words for each in MAINTAINED if each.key == language), MAINTAINED[0].words)
20
+
21
+
22
+ def server_version() -> str:
23
+ """The installed PyBreeze's version; empty when it runs from a source tree."""
24
+ try:
25
+ return installed.version("pybreeze")
26
+ except installed.PackageNotFoundError:
27
+ return ""
28
+
29
+
30
+ def ask_framework(
31
+ server: ActionLanguageServer, profile: FrameworkProfile, interpreter: str | None) -> Callable[[], list[dict]]:
32
+ """Ask *profile*'s framework for its keywords, and return what gives *server* the answer.
33
+
34
+ The asking imports the framework in a process of its own and takes
35
+ seconds: the server runs this on a thread and goes on answering.
36
+ """
37
+ try:
38
+ metadata = read_metadata(profile, interpreter)
39
+ except LanguageServiceException as error:
40
+ return partial(server.decline, profile.framework, str(error))
41
+ return partial(server.offer, metadata)
42
+
43
+
44
+ def main(arguments: list[str]) -> int:
45
+ """Serve the protocol on standard input and output until the editor says ``exit`` or goes away."""
46
+ parser = argparse.ArgumentParser(
47
+ prog="python -m pybreeze.extend.language_server",
48
+ description="Language server for WebRunner, AutoControl and LoadDensity action scripts (JSON), "
49
+ "speaking the Language Server Protocol on standard input and output.")
50
+ parser.add_argument("--interpreter", default=None,
51
+ help="the Python that runs the scripts, whose installed frameworks are asked for their "
52
+ "keywords (default: the one running this server)")
53
+ parser.add_argument("--language", default=MAINTAINED[0].key,
54
+ help="the language of the diagnostics, as the IDE names it (default: %(default)s)")
55
+ options = parser.parse_args(arguments)
56
+ server = ActionLanguageServer(words_of(options.language), server_version())
57
+ serve(server, sys.stdin.buffer, sys.stdout.buffer,
58
+ [partial(ask_framework, server, profile, options.interpreter) for profile in PROFILES])
59
+ return 0
@@ -0,0 +1,165 @@
1
+ """PyBreeze's English strings for the features that reach outside the IDE.
2
+
3
+ The frameworks' keywords and the language service that answers the editor from
4
+ them, and the MCP client. They are merged into ``pybreeze_english_word_dict``
5
+ (``extend_english.py``), which is the dictionary everything reads: this file
6
+ only keeps that one under a thousand lines.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ ENGLISH_INTEGRATION_WORDS: dict[str, str] = {
11
+ # MCP client
12
+ "extend_tools_menu_mcp_client_tab_action": "MCP Client Tab",
13
+ "extend_tools_menu_mcp_client_tab_label": "MCP Client",
14
+ "extend_tools_menu_mcp_client_dock_action": "MCP Client Dock",
15
+ "extend_tools_menu_mcp_client_dock_title": "MCP Client",
16
+ "mcp_servers_label": "Servers",
17
+ "mcp_servers_found_label": "{name} (from this project)",
18
+ "mcp_servers_add_button": "Add...",
19
+ "mcp_servers_edit_button": "Edit...",
20
+ "mcp_servers_remove_button": "Remove",
21
+ "mcp_servers_connect_button": "Connect",
22
+ "mcp_servers_disconnect_button": "Disconnect",
23
+ "mcp_servers_remove_title": "Remove a server",
24
+ "mcp_servers_remove_question": "Remove {name} from your servers?",
25
+ "mcp_page_tools": "Tools",
26
+ "mcp_page_resources": "Resources",
27
+ "mcp_page_prompts": "Prompts",
28
+ "mcp_page_calls": "Calls",
29
+ "mcp_tools_filter_placeholder": "Filter the tools",
30
+ "mcp_tools_arguments_label": "Arguments (a JSON object):",
31
+ "mcp_tools_call_button": "Call",
32
+ "mcp_tools_cancel_button": "Cancel",
33
+ "mcp_tools_hint_read_only": "The server says this tool changes nothing.",
34
+ "mcp_tools_hint_destructive": "The server says this tool may destroy or overwrite something.",
35
+ "mcp_tools_hint_unknown": "The server does not say whether this tool changes anything.",
36
+ "mcp_result_cut": "(cut here: {shown} of {whole} characters are shown)",
37
+ "mcp_resources_read_button": "Read",
38
+ "mcp_prompts_get_button": "Get",
39
+ "mcp_prompts_arguments_label": "Arguments (a JSON object of texts):",
40
+ "mcp_calls_column_when": "When",
41
+ "mcp_calls_column_tool": "Tool",
42
+ "mcp_calls_column_status": "Ended",
43
+ "mcp_calls_column_seconds": "Seconds",
44
+ "mcp_calls_status_passed": "answered",
45
+ "mcp_calls_status_failed": "failed",
46
+ "mcp_calls_status_error": "not answered",
47
+ "mcp_calls_status_skipped": "not called",
48
+ "mcp_calls_export_button": "Export Session...",
49
+ "mcp_calls_export_title": "Export the session",
50
+ "mcp_calls_file_filter": "JSON (*.json)",
51
+ "mcp_client_not_connected": "Not connected. Choose a server and connect.",
52
+ "mcp_client_servers_unreadable": "Your MCP servers could not be read: {reason}",
53
+ "mcp_client_connecting": "Connecting to {name}...",
54
+ "mcp_client_connected": "Connected to {server}: {tools} tools, {resources} resources, {prompts} prompts",
55
+ "mcp_client_disconnected": "Disconnected from {name}",
56
+ "mcp_client_failed_with_log": "{reason}. The server's log ends: {line}",
57
+ "mcp_client_arguments_not_object": "The arguments have to be a JSON object: names and their values, in braces",
58
+ "mcp_client_calling": "Calling {tool}...",
59
+ "mcp_client_called": "{tool} answered in {seconds} s",
60
+ "mcp_client_tool_failed": "{tool} ran and says it failed",
61
+ "mcp_client_declined": "{tool} was not called",
62
+ "mcp_client_fetching": "Getting {name}...",
63
+ "mcp_client_fetched": "Done",
64
+ "mcp_client_exported": "The session was saved to {file}",
65
+ "mcp_confirm_title": "Call an MCP tool",
66
+ "mcp_confirm_question": "Call {tool} on {server}?",
67
+ "mcp_confirm_arguments": "It will be called with:",
68
+ "mcp_confirm_trust": "Do not ask again for {tool} on {server}",
69
+ "mcp_found_title": "Start a server from this project",
70
+ "mcp_found_question":
71
+ "{name} comes from a file in the project folder (.mcp.json), not from your own servers. Starting it runs this command on your machine. Start it?",
72
+ "mcp_profile_dialog_title": "MCP server",
73
+ "mcp_profile_name_label": "Name:",
74
+ "mcp_profile_command_label": "Command:",
75
+ "mcp_profile_command_placeholder": "The program, then one argument on each line",
76
+ "mcp_profile_folder_label": "Start in:",
77
+ "mcp_profile_browse_button": "Browse...",
78
+ "mcp_profile_timeout_label": "Seconds a request may take:",
79
+ "mcp_profile_environment_label": "Environment variables:",
80
+ "mcp_profile_environment_note":
81
+ "Keys and tokens go here, not in the command: the command is shown when the server is started, and these values are not. They are kept in a file only you can read, and left out of the log and of exported sessions.",
82
+ "mcp_profile_variable_name": "Name",
83
+ "mcp_profile_variable_value": "Value",
84
+ "mcp_profile_add_variable_button": "Add Variable",
85
+ "mcp_profile_remove_variable_button": "Remove Variable",
86
+ "mcp_profile_show_values": "Show values",
87
+ "mcp_profile_needs_name": "A server needs a name",
88
+ "mcp_profile_name_taken": "Another server already has that name",
89
+ "mcp_profile_needs_command": "A server needs a command: the program that starts it",
90
+ # Report viewer
91
+ "extend_tools_menu_report_viewer_tab_action": "Report Viewer Tab",
92
+ "extend_tools_menu_report_viewer_tab_label": "Report Viewer",
93
+ "extend_tools_menu_report_viewer_dock_action": "Report Viewer Dock",
94
+ "extend_tools_menu_report_viewer_dock_title": "Report Viewer",
95
+ "report_status_passed": "passed",
96
+ "report_status_failed": "failed",
97
+ "report_status_error": "error",
98
+ "report_status_skipped": "skipped",
99
+ "report_column_name": "Name",
100
+ "report_column_status": "Ended",
101
+ "report_column_seconds": "Seconds",
102
+ "report_html_detail": "What it said",
103
+ "report_html_output": "Output",
104
+ "report_html_seconds": "{seconds} s",
105
+ "report_format_json": "Execution report",
106
+ "report_format_junit": "JUnit XML",
107
+ "report_format_html": "HTML page",
108
+ "report_viewer_open_button": "Open...",
109
+ "report_viewer_export_button": "Export...",
110
+ "report_viewer_close_button": "Close Report",
111
+ "report_viewer_at_least_label": "At least (s):",
112
+ "report_viewer_every_framework": "Every package",
113
+ "report_viewer_filter_placeholder": "Filter by name or error",
114
+ "report_viewer_tab_details": "Details",
115
+ "report_viewer_tab_output": "Output",
116
+ "report_viewer_tab_attachments": "Attachments",
117
+ "report_viewer_tab_raw": "Own record",
118
+ "report_viewer_open_title": "Open reports",
119
+ "report_viewer_open_filter": "Reports (*.json *.xml *.html *.htm);;All Files (*)",
120
+ "report_viewer_export_title": "Export the report",
121
+ "report_viewer_not_read": "{file} was not opened: {reason}",
122
+ "report_viewer_exported": "The report was saved to {file}",
123
+ "report_viewer_nothing_open":
124
+ "No report is open. Open a package's _success or _failure file, JUnit XML, or an exported report.",
125
+ "report_viewer_summary": "{shown} of {every} results shown, from {runs} reports, {seconds} s",
126
+ "mcp_calls_view_button": "Open in Report Viewer",
127
+ # Automation keywords
128
+ "keyword_reference_framework_label": "Framework:",
129
+ "keyword_reference_refresh_button": "Read Again",
130
+ "keyword_reference_search_placeholder": "Filter by name or description",
131
+ "keyword_reference_copy_button": "Copy as Action",
132
+ "keyword_reference_loading": "Reading the keywords of {framework}...",
133
+ "keyword_reference_ready": "{framework}: {count} keywords. In a .json script the editor offers "
134
+ "{capabilities}",
135
+ "keyword_reference_capability_completion": "completion",
136
+ "keyword_reference_capability_diagnostics": "diagnostics",
137
+ "keyword_reference_capability_hover": "hover",
138
+ "keyword_reference_capability_definition": "go to definition",
139
+ "keyword_reference_defined_in": "Defined in {file}, line {line}",
140
+ "keyword_reference_no_interpreter": "No Python interpreter was found to read the keywords with",
141
+ # Language service for action scripts (diagnostics and hover, shown by the editor)
142
+ "language_service_json_syntax": "This is not valid JSON",
143
+ "language_service_unknown_keyword": "{name} is not a keyword of {framework}",
144
+ "language_service_unknown_keyword_suggestion":
145
+ "{name} is not a keyword of {framework}. Did you mean {suggestion}?",
146
+ "language_service_unknown_parameter": "{keyword} has no parameter named {name}",
147
+ "language_service_unknown_parameter_suggestion":
148
+ "{keyword} has no parameter named {name}. Did you mean {suggestion}?",
149
+ "language_service_missing_parameter": "{keyword} needs {names}",
150
+ "language_service_too_many_values":
151
+ "{keyword} takes at most {most} values in a list, and this one gives {count}",
152
+ "language_service_too_few_values":
153
+ "{keyword} needs at least {least} values in a list, and this one gives {count}",
154
+ "language_service_needs_names":
155
+ "{keyword} takes {names} by name only: give an object of named values, not a list",
156
+ "language_service_action_not_list":
157
+ "An action is a list: [\"keyword\"] or [\"keyword\", arguments]",
158
+ "language_service_action_no_keyword": "An action starts with its keyword, in quotes",
159
+ "language_service_action_too_long": "An action holds a keyword and at most one set of arguments",
160
+ "language_service_arguments_shape":
161
+ "Arguments are an object of named values, or a list of values",
162
+ "language_service_actions_not_list": "{key} holds a list of actions",
163
+ "language_service_parameter_required": "required",
164
+ "language_service_parameter_optional": "optional",
165
+ }