auto-coder 0.1.348__tar.gz → 0.1.349__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.

Potentially problematic release.


This version of auto-coder might be problematic. Click here for more details.

Files changed (290) hide show
  1. {auto_coder-0.1.348 → auto_coder-0.1.349}/PKG-INFO +1 -1
  2. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/auto_coder.egg-info/PKG-INFO +1 -1
  3. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/auto_coder.egg-info/SOURCES.txt +9 -2
  4. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/auto_coder_runner.py +14 -10
  5. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/chat_auto_coder_lang.py +5 -3
  6. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/printer.py +7 -8
  7. auto_coder-0.1.349/src/autocoder/common/run_cmd.py +247 -0
  8. auto_coder-0.1.349/src/autocoder/common/test_run_cmd.py +110 -0
  9. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit.py +61 -11
  10. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_conversation.py +9 -0
  11. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +21 -36
  12. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +4 -7
  13. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +2 -5
  14. auto_coder-0.1.349/src/autocoder/helper/rag_doc_creator.py +141 -0
  15. auto_coder-0.1.349/src/autocoder/ignorefiles/__init__.py +4 -0
  16. auto_coder-0.1.349/src/autocoder/ignorefiles/ignore_file_utils.py +63 -0
  17. auto_coder-0.1.349/src/autocoder/ignorefiles/test_ignore_file_utils.py +91 -0
  18. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/models.py +49 -9
  19. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/cache/byzer_storage_cache.py +10 -4
  20. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/cache/file_monitor_cache.py +27 -24
  21. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/cache/local_byzer_storage_cache.py +11 -5
  22. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/cache/local_duckdb_storage_cache.py +203 -128
  23. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/cache/simple_cache.py +56 -37
  24. auto_coder-0.1.349/src/autocoder/rag/loaders/filter_utils.py +106 -0
  25. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/loaders/image_loader.py +45 -23
  26. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/loaders/pdf_loader.py +3 -3
  27. auto_coder-0.1.349/src/autocoder/rag/loaders/test_image_loader.py +209 -0
  28. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/qa_conversation_strategy.py +3 -5
  29. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/utils.py +20 -9
  30. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/_markitdown.py +35 -0
  31. auto_coder-0.1.349/src/autocoder/version.py +1 -0
  32. auto_coder-0.1.348/src/autocoder/common/v2/agent/ignore_utils.py +0 -50
  33. auto_coder-0.1.348/src/autocoder/version.py +0 -1
  34. {auto_coder-0.1.348 → auto_coder-0.1.349}/LICENSE +0 -0
  35. {auto_coder-0.1.348 → auto_coder-0.1.349}/README.md +0 -0
  36. {auto_coder-0.1.348 → auto_coder-0.1.349}/setup.cfg +0 -0
  37. {auto_coder-0.1.348 → auto_coder-0.1.349}/setup.py +0 -0
  38. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/auto_coder.egg-info/dependency_links.txt +0 -0
  39. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/auto_coder.egg-info/entry_points.txt +0 -0
  40. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/auto_coder.egg-info/requires.txt +0 -0
  41. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/auto_coder.egg-info/top_level.txt +0 -0
  42. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/__init__.py +0 -0
  43. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/agent/__init__.py +0 -0
  44. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/agent/agentic_filter.py +0 -0
  45. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/agent/auto_demand_organizer.py +0 -0
  46. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/agent/auto_filegroup.py +0 -0
  47. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/agent/auto_guess_query.py +0 -0
  48. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/agent/auto_learn_from_commit.py +0 -0
  49. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/agent/auto_review_commit.py +0 -0
  50. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/agent/auto_tool.py +0 -0
  51. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/agent/coder.py +0 -0
  52. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/agent/designer.py +0 -0
  53. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/agent/planner.py +0 -0
  54. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/agent/project_reader.py +0 -0
  55. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/auto_coder.py +0 -0
  56. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/auto_coder_rag.py +0 -0
  57. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/auto_coder_server.py +0 -0
  58. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/benchmark.py +0 -0
  59. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/chat/__init__.py +0 -0
  60. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/chat_auto_coder.py +0 -0
  61. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/command_args.py +0 -0
  62. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/command_parser.py +0 -0
  63. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/commands/__init__.py +0 -0
  64. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/commands/auto_command.py +0 -0
  65. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/commands/auto_web.py +0 -0
  66. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/commands/tools.py +0 -0
  67. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/JupyterClient.py +0 -0
  68. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/ShellClient.py +0 -0
  69. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/__init__.py +0 -0
  70. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/action_yml_file_manager.py +0 -0
  71. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/anything2images.py +0 -0
  72. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/anything2img.py +0 -0
  73. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/audio.py +0 -0
  74. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/auto_coder_lang.py +0 -0
  75. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/auto_configure.py +0 -0
  76. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/buildin_tokenizer.py +0 -0
  77. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/chunk_validation.py +0 -0
  78. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/cleaner.py +0 -0
  79. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/code_auto_execute.py +0 -0
  80. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/code_auto_generate.py +0 -0
  81. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/code_auto_generate_diff.py +0 -0
  82. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/code_auto_generate_editblock.py +0 -0
  83. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/code_auto_generate_strict_diff.py +0 -0
  84. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/code_auto_merge.py +0 -0
  85. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/code_auto_merge_diff.py +0 -0
  86. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/code_auto_merge_editblock.py +0 -0
  87. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/code_auto_merge_strict_diff.py +0 -0
  88. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/code_modification_ranker.py +0 -0
  89. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/command_completer.py +0 -0
  90. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/command_generator.py +0 -0
  91. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/command_templates.py +0 -0
  92. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/computer_use.py +0 -0
  93. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/conf_import_export.py +0 -0
  94. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/conf_utils.py +0 -0
  95. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/conf_validator.py +0 -0
  96. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/const.py +0 -0
  97. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/context_pruner.py +0 -0
  98. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/conversation_pruner.py +0 -0
  99. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/files.py +0 -0
  100. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/git_utils.py +0 -0
  101. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/global_cancel.py +0 -0
  102. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/image_to_page.py +0 -0
  103. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/index_import_export.py +0 -0
  104. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/interpreter.py +0 -0
  105. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/llm_rerank.py +0 -0
  106. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/mcp_hub.py +0 -0
  107. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/mcp_server.py +0 -0
  108. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/mcp_server_install.py +0 -0
  109. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/mcp_server_types.py +0 -0
  110. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/mcp_servers/__init__.py +0 -0
  111. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/mcp_servers/mcp_server_gpt4o_mini_search.py +0 -0
  112. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/mcp_servers/mcp_server_perplexity.py +0 -0
  113. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/mcp_tools.py +0 -0
  114. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/memory_manager.py +0 -0
  115. /auto_coder-0.1.348/src/autocoder/common/model_speed_test.py → /auto_coder-0.1.349/src/autocoder/common/model_speed_tester.py +0 -0
  116. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/openai_content.py +0 -0
  117. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/recall_validation.py +0 -0
  118. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/result_manager.py +0 -0
  119. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/screenshots.py +0 -0
  120. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/search.py +0 -0
  121. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/search_replace.py +0 -0
  122. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/shells.py +0 -0
  123. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/stats_panel.py +0 -0
  124. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/stream_out_type.py +0 -0
  125. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/sys_prompt.py +0 -0
  126. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/text.py +0 -0
  127. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/token_cost_caculate.py +0 -0
  128. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/types.py +0 -0
  129. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/utils_code_auto_generate.py +0 -0
  130. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/__init__.py +0 -0
  131. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/__init__.py +0 -0
  132. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/__init__.py +0 -0
  133. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +0 -0
  134. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/attempt_completion_tool_resolver.py +0 -0
  135. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py +0 -0
  136. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/list_code_definition_names_tool_resolver.py +0 -0
  137. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py +0 -0
  138. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/plan_mode_respond_tool_resolver.py +0 -0
  139. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +0 -0
  140. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +0 -0
  141. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/use_mcp_tool_resolver.py +0 -0
  142. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +0 -0
  143. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_edit_types.py +0 -0
  144. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/agent/agentic_tool_display.py +0 -0
  145. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_agentic_editblock_manager.py +0 -0
  146. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_auto_generate.py +0 -0
  147. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_auto_generate_diff.py +0 -0
  148. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_auto_generate_editblock.py +0 -0
  149. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_auto_generate_strict_diff.py +0 -0
  150. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_auto_merge.py +0 -0
  151. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_auto_merge_diff.py +0 -0
  152. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_auto_merge_editblock.py +0 -0
  153. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_auto_merge_strict_diff.py +0 -0
  154. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_diff_manager.py +0 -0
  155. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_editblock_manager.py +0 -0
  156. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_manager.py +0 -0
  157. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/common/v2/code_strict_diff_manager.py +0 -0
  158. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/compilers/__init__.py +0 -0
  159. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/compilers/base_compiler.py +0 -0
  160. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/compilers/compiler_config_api.py +0 -0
  161. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/compilers/compiler_config_manager.py +0 -0
  162. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/compilers/compiler_factory.py +0 -0
  163. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/compilers/java_compiler.py +0 -0
  164. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/compilers/models.py +0 -0
  165. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/compilers/provided_compiler.py +0 -0
  166. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/compilers/python_compiler.py +0 -0
  167. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/compilers/reactjs_compiler.py +0 -0
  168. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/compilers/shadow_compiler.py +0 -0
  169. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/compilers/vue_compiler.py +0 -0
  170. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/data/byzerllm.md +0 -0
  171. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/data/tokenizer.json +0 -0
  172. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/db/__init__.py +0 -0
  173. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/db/store.py +0 -0
  174. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/dispacher/__init__.py +0 -0
  175. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/dispacher/actions/__init__.py +0 -0
  176. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/dispacher/actions/action.py +0 -0
  177. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/dispacher/actions/copilot.py +0 -0
  178. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/dispacher/actions/plugins/__init__.py +0 -0
  179. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/dispacher/actions/plugins/action_regex_project.py +0 -0
  180. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/events/__init__.py +0 -0
  181. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/events/event_content.py +0 -0
  182. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/events/event_manager.py +0 -0
  183. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/events/event_manager_singleton.py +0 -0
  184. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/events/event_store.py +0 -0
  185. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/events/event_types.py +0 -0
  186. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/helper/__init__.py +0 -0
  187. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/helper/project_creator.py +0 -0
  188. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/index/__init__.py +0 -0
  189. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/index/entry.py +0 -0
  190. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/index/filter/__init__.py +0 -0
  191. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/index/filter/normal_filter.py +0 -0
  192. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/index/filter/quick_filter.py +0 -0
  193. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/index/for_command.py +0 -0
  194. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/index/index.py +0 -0
  195. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/index/symbols_utils.py +0 -0
  196. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/index/types.py +0 -0
  197. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/lang.py +0 -0
  198. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/linters/__init__.py +0 -0
  199. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/linters/base_linter.py +0 -0
  200. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/linters/linter_factory.py +0 -0
  201. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/linters/models.py +0 -0
  202. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/linters/python_linter.py +0 -0
  203. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/linters/reactjs_linter.py +0 -0
  204. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/linters/shadow_linter.py +0 -0
  205. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/linters/vue_linter.py +0 -0
  206. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/memory/__init__.py +0 -0
  207. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/memory/active_context_manager.py +0 -0
  208. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/memory/active_package.py +0 -0
  209. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/memory/async_processor.py +0 -0
  210. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/memory/directory_mapper.py +0 -0
  211. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/plugins/__init__.py +0 -0
  212. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/plugins/dynamic_completion_example.py +0 -0
  213. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/plugins/git_helper_plugin.py +0 -0
  214. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/plugins/sample_plugin.py +0 -0
  215. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/plugins/token_helper_plugin.py +0 -0
  216. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/plugins/utils.py +0 -0
  217. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/privacy/__init__.py +0 -0
  218. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/privacy/model_filter.py +0 -0
  219. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/pyproject/__init__.py +0 -0
  220. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/__init__.py +0 -0
  221. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/api_server.py +0 -0
  222. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/cache/__init__.py +0 -0
  223. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/cache/base_cache.py +0 -0
  224. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/cache/cache_result_merge.py +0 -0
  225. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/cache/failed_files_utils.py +0 -0
  226. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/cache/rag_file_meta.py +0 -0
  227. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/conversation_to_queries.py +0 -0
  228. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/doc_filter.py +0 -0
  229. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/document_retriever.py +0 -0
  230. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/lang.py +0 -0
  231. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/llm_wrapper.py +0 -0
  232. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/loaders/__init__.py +0 -0
  233. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/loaders/docx_loader.py +0 -0
  234. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/loaders/excel_loader.py +0 -0
  235. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/loaders/ppt_loader.py +0 -0
  236. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/long_context_rag.py +0 -0
  237. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/rag_config.py +0 -0
  238. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/rag_entry.py +0 -0
  239. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/raw_rag.py +0 -0
  240. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/relevant_utils.py +0 -0
  241. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/searchable.py +0 -0
  242. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/simple_directory_reader.py +0 -0
  243. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/simple_rag.py +0 -0
  244. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/stream_event/__init__.py +0 -0
  245. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/stream_event/event_writer.py +0 -0
  246. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/stream_event/types.py +0 -0
  247. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/token_checker.py +0 -0
  248. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/token_counter.py +0 -0
  249. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/token_limiter.py +0 -0
  250. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/token_limiter_utils.py +0 -0
  251. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/types.py +0 -0
  252. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/rag/variable_holder.py +0 -0
  253. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/regexproject/__init__.py +0 -0
  254. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/run_context.py +0 -0
  255. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/shadows/__init__.py +0 -0
  256. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/shadows/shadow_manager.py +0 -0
  257. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/suffixproject/__init__.py +0 -0
  258. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/tsproject/__init__.py +0 -0
  259. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/__init__.py +0 -0
  260. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/auto_coder_utils/__init__.py +0 -0
  261. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/auto_coder_utils/chat_stream_out.py +0 -0
  262. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/auto_project_type.py +0 -0
  263. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/chat_auto_coder_utils/__init__.py +0 -0
  264. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/conversation_store.py +0 -0
  265. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/llm_client_interceptors.py +0 -0
  266. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/llms.py +0 -0
  267. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/log_capture.py +0 -0
  268. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/model_provider_selector.py +0 -0
  269. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/multi_turn.py +0 -0
  270. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/operate_config_api.py +0 -0
  271. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/print_table.py +0 -0
  272. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/project_structure.py +0 -0
  273. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/queue_communicate.py +0 -0
  274. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/request_event_queue.py +0 -0
  275. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/request_queue.py +0 -0
  276. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/rest.py +0 -0
  277. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/stream_thinking.py +0 -0
  278. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/tests.py +0 -0
  279. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/thread_utils.py +0 -0
  280. {auto_coder-0.1.348 → auto_coder-0.1.349}/src/autocoder/utils/types.py +0 -0
  281. {auto_coder-0.1.348 → auto_coder-0.1.349}/tests/test_action_regex_project.py +0 -0
  282. {auto_coder-0.1.348 → auto_coder-0.1.349}/tests/test_action_yml_file_manager.py +0 -0
  283. {auto_coder-0.1.348 → auto_coder-0.1.349}/tests/test_chat_auto_coder.py +0 -0
  284. {auto_coder-0.1.348 → auto_coder-0.1.349}/tests/test_code_auto_merge_editblock.py +0 -0
  285. {auto_coder-0.1.348 → auto_coder-0.1.349}/tests/test_command_completer.py +0 -0
  286. {auto_coder-0.1.348 → auto_coder-0.1.349}/tests/test_planner.py +0 -0
  287. {auto_coder-0.1.348 → auto_coder-0.1.349}/tests/test_plugins.py +0 -0
  288. {auto_coder-0.1.348 → auto_coder-0.1.349}/tests/test_privacy.py +0 -0
  289. {auto_coder-0.1.348 → auto_coder-0.1.349}/tests/test_queue_communicate.py +0 -0
  290. {auto_coder-0.1.348 → auto_coder-0.1.349}/tests/test_symbols_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-coder
3
- Version: 0.1.348
3
+ Version: 0.1.349
4
4
  Summary: AutoCoder: AutoCoder
5
5
  Author: allwefantasy
6
6
  Classifier: Programming Language :: Python :: 3.10
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-coder
3
- Version: 0.1.348
3
+ Version: 0.1.349
4
4
  Summary: AutoCoder: AutoCoder
5
5
  Author: allwefantasy
6
6
  Classifier: Programming Language :: Python :: 3.10
@@ -83,11 +83,12 @@ src/autocoder/common/mcp_server_install.py
83
83
  src/autocoder/common/mcp_server_types.py
84
84
  src/autocoder/common/mcp_tools.py
85
85
  src/autocoder/common/memory_manager.py
86
- src/autocoder/common/model_speed_test.py
86
+ src/autocoder/common/model_speed_tester.py
87
87
  src/autocoder/common/openai_content.py
88
88
  src/autocoder/common/printer.py
89
89
  src/autocoder/common/recall_validation.py
90
90
  src/autocoder/common/result_manager.py
91
+ src/autocoder/common/run_cmd.py
91
92
  src/autocoder/common/screenshots.py
92
93
  src/autocoder/common/search.py
93
94
  src/autocoder/common/search_replace.py
@@ -95,6 +96,7 @@ src/autocoder/common/shells.py
95
96
  src/autocoder/common/stats_panel.py
96
97
  src/autocoder/common/stream_out_type.py
97
98
  src/autocoder/common/sys_prompt.py
99
+ src/autocoder/common/test_run_cmd.py
98
100
  src/autocoder/common/text.py
99
101
  src/autocoder/common/token_cost_caculate.py
100
102
  src/autocoder/common/types.py
@@ -121,7 +123,6 @@ src/autocoder/common/v2/agent/agentic_edit.py
121
123
  src/autocoder/common/v2/agent/agentic_edit_conversation.py
122
124
  src/autocoder/common/v2/agent/agentic_edit_types.py
123
125
  src/autocoder/common/v2/agent/agentic_tool_display.py
124
- src/autocoder/common/v2/agent/ignore_utils.py
125
126
  src/autocoder/common/v2/agent/agentic_edit_tools/__init__.py
126
127
  src/autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py
127
128
  src/autocoder/common/v2/agent/agentic_edit_tools/attempt_completion_tool_resolver.py
@@ -166,6 +167,10 @@ src/autocoder/events/event_store.py
166
167
  src/autocoder/events/event_types.py
167
168
  src/autocoder/helper/__init__.py
168
169
  src/autocoder/helper/project_creator.py
170
+ src/autocoder/helper/rag_doc_creator.py
171
+ src/autocoder/ignorefiles/__init__.py
172
+ src/autocoder/ignorefiles/ignore_file_utils.py
173
+ src/autocoder/ignorefiles/test_ignore_file_utils.py
169
174
  src/autocoder/index/__init__.py
170
175
  src/autocoder/index/entry.py
171
176
  src/autocoder/index/for_command.py
@@ -233,9 +238,11 @@ src/autocoder/rag/cache/simple_cache.py
233
238
  src/autocoder/rag/loaders/__init__.py
234
239
  src/autocoder/rag/loaders/docx_loader.py
235
240
  src/autocoder/rag/loaders/excel_loader.py
241
+ src/autocoder/rag/loaders/filter_utils.py
236
242
  src/autocoder/rag/loaders/image_loader.py
237
243
  src/autocoder/rag/loaders/pdf_loader.py
238
244
  src/autocoder/rag/loaders/ppt_loader.py
245
+ src/autocoder/rag/loaders/test_image_loader.py
239
246
  src/autocoder/rag/stream_event/__init__.py
240
247
  src/autocoder/rag/stream_event/event_writer.py
241
248
  src/autocoder/rag/stream_event/types.py
@@ -2019,9 +2019,9 @@ def manage_models(query: str):
2019
2019
  /models /add_model name=xxx base_url=xxx ... - Add model with custom params
2020
2020
  /models /remove <name> - Remove model by name
2021
2021
  """
2022
- printer = Printer()
2023
2022
  console = Console()
2024
-
2023
+ printer = Printer(console=console)
2024
+
2025
2025
  product_mode = memory.get("product_mode", "lite")
2026
2026
  if product_mode != "lite":
2027
2027
  printer.print_in_terminal("models_lite_only", style="red")
@@ -2246,7 +2246,7 @@ def manage_models(query: str):
2246
2246
  printer.print_in_terminal("models_speed_usage", style="red")
2247
2247
 
2248
2248
  elif subcmd == "/speed-test":
2249
- from autocoder.common.model_speed_test import render_speed_test_in_terminal
2249
+ from autocoder.common.model_speed_tester import render_speed_test_in_terminal
2250
2250
  test_rounds = 1 # 默认测试轮数
2251
2251
 
2252
2252
  enable_long_context = False
@@ -2274,7 +2274,7 @@ def manage_models(query: str):
2274
2274
 
2275
2275
  elif subcmd == "/add":
2276
2276
  # Support both simplified and legacy formats
2277
- args = query.strip().split(" ")
2277
+ args = query.strip().split(" ")
2278
2278
  if len(args) == 2:
2279
2279
  # Simplified: /models /add <name> <api_key>
2280
2280
  name, api_key = args[0], args[1]
@@ -2295,9 +2295,10 @@ def manage_models(query: str):
2295
2295
  }
2296
2296
  })
2297
2297
  printer.print_in_terminal("models_add_failed", style="red", name=name)
2298
- else:
2299
- printer.print_in_terminal("models_add_usage", style="red")
2300
- result_manager.add_result(content=printer.get_message_from_key("models_add_usage"),meta={
2298
+ else:
2299
+ models_list = "\n".join([m["name"] for m in models_module.default_models_list])
2300
+ printer.print_in_terminal("models_add_usage", style="red", models=models_list)
2301
+ result_manager.add_result(content=printer.get_message_from_key_with_format("models_add_usage",models=models_list),meta={
2301
2302
  "action": "models",
2302
2303
  "input": {
2303
2304
  "query": query
@@ -2828,8 +2829,11 @@ def auto_command(query: str,extra_args: Dict[str,Any]={}):
2828
2829
  current_files = memory.get("current_files",{}).get("files",[])
2829
2830
  sources = []
2830
2831
  for file in current_files:
2831
- with open(file,"r",encoding="utf-8") as f:
2832
- sources.append(SourceCode(module_name=file,source_code=f.read()))
2832
+ try:
2833
+ with open(file,"r",encoding="utf-8") as f:
2834
+ sources.append(SourceCode(module_name=file,source_code=f.read()))
2835
+ except Exception as e:
2836
+ global_logger.error(f"Failed to read file {file}: {e}")
2833
2837
 
2834
2838
  llm = get_single_llm(args.code_model or args.model,product_mode=args.product_mode)
2835
2839
  conversation_history = extra_args.get("conversations",[])
@@ -2895,4 +2899,4 @@ def auto_command(query: str,extra_args: Dict[str,Any]={}):
2895
2899
  title=printer.get_message_from_key_with_format("auto_command_reasoning_title"),
2896
2900
  border_style="blue",
2897
2901
  padding=(1, 2)
2898
- ))
2902
+ ))
@@ -387,8 +387,8 @@ MESSAGES = {
387
387
  "zh": "添加模型 '{{name}}' 失败。在默认模型中未找到该模型。"
388
388
  },
389
389
  "models_add_usage": {
390
- "en": "Usage: /models /add <name> <api_key> or\n/models /add <name> <model_type> <model_name> <base_url> <api_key_path> [description]",
391
- "zh": "用法: /models /add <name> <api_key> 或\n/models /add <name> <model_type> <model_name> <base_url> <api_key_path> [description]"
390
+ "en": "Usage: /models /add <name> <api_key> \n Available models: \n{{models}}",
391
+ "zh": "用法: /models /add <name> <api_key> \n 可用模型: \n{{models}}"
392
392
  },
393
393
  "models_add_model_params": {
394
394
  "en": "Please provide parameters in key=value format",
@@ -582,7 +582,9 @@ def get_system_language():
582
582
 
583
583
  def get_message(key):
584
584
  lang = get_system_language()
585
- return MESSAGES.get(key, {}).get(lang, MESSAGES[key].get("en", ""))
585
+ if key in MESSAGES:
586
+ return MESSAGES[key].get(lang, MESSAGES[key].get("en", ""))
587
+ return ""
586
588
 
587
589
 
588
590
  def get_message_with_format(msg_key: str, **kwargs):
@@ -15,19 +15,18 @@ class Printer:
15
15
 
16
16
  def get_message_from_key(self, msg_key: str):
17
17
  try:
18
- return get_message(msg_key)
18
+ v = get_message(msg_key)
19
+ if not v:
20
+ return get_chat_message(msg_key)
19
21
  except Exception as e:
20
22
  return get_chat_message(msg_key)
21
23
 
22
- def get_message_from_key_with_format(self, msg_key: str, **kwargs):
23
- try:
24
- return format_str_jinja2(self.get_message_from_key(msg_key), **kwargs)
25
- except Exception as e:
26
- return format_str_jinja2(self.get_chat_message_from_key(msg_key), **kwargs)
27
-
24
+ def get_message_from_key_with_format(self, msg_key: str, **kwargs):
25
+ return format_str_jinja2(self.get_message_from_key(msg_key), **kwargs)
26
+
28
27
  def print_in_terminal(self, msg_key: str, style: str = None,**kwargs):
29
28
  try:
30
- if style:
29
+ if style:
31
30
  self.console.print(format_str_jinja2(self.get_message_from_key(msg_key),**kwargs), style=style)
32
31
  else:
33
32
  self.console.print(format_str_jinja2(self.get_message_from_key(msg_key),**kwargs))
@@ -0,0 +1,247 @@
1
+ import os
2
+ import platform
3
+ import subprocess
4
+ import sys
5
+ from io import BytesIO
6
+
7
+ import pexpect
8
+ import psutil
9
+
10
+
11
+ def run_cmd(command, verbose=False, error_print=None, cwd=None):
12
+ """
13
+ 执行一条命令,根据不同系统和环境选择最合适的执行方式(交互式或非交互式)。
14
+
15
+ 适用场景:
16
+ - 需要跨平台运行命令,自动判断是否使用pexpect(支持交互式)还是subprocess。
17
+ - 希望获得命令的执行状态及输出内容。
18
+ - 在CLI工具、自动化脚本、REPL中执行shell命令。
19
+
20
+ 参数:
21
+ - command (str): 需要执行的命令字符串。
22
+ - verbose (bool): 是否打印详细调试信息,默认为False。
23
+ - error_print (callable|None): 自定义错误打印函数,默认为None,使用print。
24
+ - cwd (str|None): 指定命令的工作目录,默认为None。
25
+
26
+ 返回:
27
+ - tuple: (exit_code, output),其中exit_code为整型退出码,output为命令输出内容。
28
+
29
+ 异常:
30
+ - 捕获OSError异常,返回错误信息。
31
+ """
32
+ try:
33
+ if sys.stdin.isatty() and hasattr(pexpect, "spawn") and platform.system() != "Windows":
34
+ return run_cmd_pexpect(command, verbose, cwd)
35
+
36
+ return run_cmd_subprocess(command, verbose, cwd)
37
+ except OSError as e:
38
+ error_message = f"Error occurred while running command '{command}': {str(e)}"
39
+ if error_print is None:
40
+ print(error_message)
41
+ else:
42
+ error_print(error_message)
43
+ return 1, error_message
44
+
45
+
46
+ def get_windows_parent_process_name():
47
+ """
48
+ 获取当前进程的父进程名(仅在Windows系统下有意义)。
49
+
50
+ 适用场景:
51
+ - 判断命令是否由PowerShell或cmd.exe启动,以便调整命令格式。
52
+ - 在Windows平台上进行父进程分析。
53
+
54
+ 参数:
55
+ - 无
56
+
57
+ 返回:
58
+ - str|None: 父进程名(小写字符串,如"powershell.exe"或"cmd.exe"),如果无法获取则为None。
59
+
60
+ 异常:
61
+ - 捕获所有异常,返回None。
62
+ """
63
+ try:
64
+ current_process = psutil.Process()
65
+ while True:
66
+ parent = current_process.parent()
67
+ if parent is None:
68
+ break
69
+ parent_name = parent.name().lower()
70
+ if parent_name in ["powershell.exe", "cmd.exe"]:
71
+ return parent_name
72
+ current_process = parent
73
+ return None
74
+ except Exception:
75
+ return None
76
+
77
+
78
+ def run_cmd_subprocess(command, verbose=False, cwd=None, encoding=sys.stdout.encoding):
79
+ if verbose:
80
+ print("Using run_cmd_subprocess:", command)
81
+
82
+ try:
83
+ shell = os.environ.get("SHELL", "/bin/sh")
84
+ parent_process = None
85
+
86
+ # Determine the appropriate shell
87
+ if platform.system() == "Windows":
88
+ parent_process = get_windows_parent_process_name()
89
+ if parent_process == "powershell.exe":
90
+ command = f"powershell -Command {command}"
91
+
92
+ if verbose:
93
+ print("Running command:", command)
94
+ print("SHELL:", shell)
95
+ if platform.system() == "Windows":
96
+ print("Parent process:", parent_process)
97
+
98
+ process = subprocess.Popen(
99
+ command,
100
+ stdout=subprocess.PIPE,
101
+ stderr=subprocess.STDOUT,
102
+ text=True,
103
+ shell=True,
104
+ encoding=encoding,
105
+ errors="replace",
106
+ bufsize=0, # Set bufsize to 0 for unbuffered output
107
+ universal_newlines=True,
108
+ cwd=cwd,
109
+ )
110
+
111
+ output = []
112
+ while True:
113
+ chunk = process.stdout.read(1)
114
+ if not chunk:
115
+ break
116
+ print(chunk, end="", flush=True) # Print the chunk in real-time
117
+ output.append(chunk) # Store the chunk for later use
118
+
119
+ process.wait()
120
+ return process.returncode, "".join(output)
121
+ except Exception as e:
122
+ return 1, str(e)
123
+
124
+ def run_cmd_subprocess_generator(command, verbose=False, cwd=None, encoding=sys.stdout.encoding):
125
+ """
126
+ 使用subprocess运行命令,将命令输出逐步以生成器方式yield出来。
127
+
128
+ 适用场景:
129
+ - 运行无需交互的命令。
130
+ - 希望实时逐步处理命令输出(如日志打印、进度监控)。
131
+ - 在Linux、macOS、Windows等多平台环境下安全运行命令。
132
+
133
+ 参数:
134
+ - command (str): 需要执行的命令字符串。
135
+ - verbose (bool): 是否打印详细调试信息,默认为False。
136
+ - cwd (str|None): 指定命令的工作目录,默认为None。
137
+ - encoding (str): 输出解码使用的字符编码,默认为当前stdout编码。
138
+
139
+ 返回:
140
+ - 生成器: 逐块yield命令的输出字符串。
141
+
142
+ 异常:
143
+ - 捕获所有异常,yield错误信息字符串。
144
+ """
145
+ if verbose:
146
+ print("Using run_cmd_subprocess:", command)
147
+
148
+ try:
149
+ shell = os.environ.get("SHELL", "/bin/sh")
150
+ parent_process = None
151
+
152
+ # Windows下调整命令
153
+ if platform.system() == "Windows":
154
+ parent_process = get_windows_parent_process_name()
155
+ if parent_process == "powershell.exe":
156
+ command = f"powershell -Command {command}"
157
+
158
+ if verbose:
159
+ print("Running command:", command)
160
+ print("SHELL:", shell)
161
+ if platform.system() == "Windows":
162
+ print("Parent process:", parent_process)
163
+
164
+ process = subprocess.Popen(
165
+ command,
166
+ stdout=subprocess.PIPE,
167
+ stderr=subprocess.STDOUT,
168
+ text=True,
169
+ shell=True,
170
+ encoding=encoding,
171
+ errors="replace",
172
+ bufsize=0,
173
+ universal_newlines=True,
174
+ cwd=cwd,
175
+ )
176
+
177
+ while True:
178
+ chunk = process.stdout.read(1)
179
+ if not chunk:
180
+ break
181
+ # 确保始终yield字符串,避免因字节或其他类型导致异常
182
+ if not isinstance(chunk, str):
183
+ chunk = str(chunk)
184
+ yield chunk
185
+
186
+ process.wait()
187
+ except Exception as e:
188
+ # 出错时yield异常信息,也可以raise
189
+ yield f"[run_cmd_subprocess error]: {str(e)}"
190
+
191
+
192
+ def run_cmd_pexpect(command, verbose=False, cwd=None):
193
+ """
194
+ 使用pexpect以交互方式运行命令,捕获完整输出。
195
+
196
+ 适用场景:
197
+ - 执行需要用户交互的命令(如登录、密码输入等)。
198
+ - 在Linux、macOS等Unix系统下模拟终端操作。
199
+ - 希望完整捕获交互式命令的输出。
200
+
201
+ 参数:
202
+ - command (str): 需要执行的命令字符串。
203
+ - verbose (bool): 是否打印详细调试信息,默认为False。
204
+ - cwd (str|None): 指定命令的工作目录,默认为None。
205
+
206
+ 返回:
207
+ - tuple: (exit_code, output),exit_code为退出状态码,output为命令完整输出内容。
208
+
209
+ 异常:
210
+ - 捕获pexpect相关异常,返回错误信息。
211
+ """
212
+ if verbose:
213
+ print("Using run_cmd_pexpect:", command)
214
+
215
+ output = BytesIO()
216
+
217
+ def output_callback(b):
218
+ output.write(b)
219
+ return b
220
+
221
+ try:
222
+ # Use the SHELL environment variable, falling back to /bin/sh if not set
223
+ shell = os.environ.get("SHELL", "/bin/sh")
224
+ if verbose:
225
+ print("With shell:", shell)
226
+
227
+ if os.path.exists(shell):
228
+ # Use the shell from SHELL environment variable
229
+ if verbose:
230
+ print("Running pexpect.spawn with shell:", shell)
231
+ child = pexpect.spawn(shell, args=["-i", "-c", command], encoding="utf-8", cwd=cwd)
232
+ else:
233
+ # Fall back to spawning the command directly
234
+ if verbose:
235
+ print("Running pexpect.spawn without shell.")
236
+ child = pexpect.spawn(command, encoding="utf-8", cwd=cwd)
237
+
238
+ # Transfer control to the user, capturing output
239
+ child.interact(output_filter=output_callback)
240
+
241
+ # Wait for the command to finish and get the exit status
242
+ child.close()
243
+ return child.exitstatus, output.getvalue().decode("utf-8", errors="replace")
244
+
245
+ except (pexpect.ExceptionPexpect, TypeError, ValueError) as e:
246
+ error_msg = f"Error running command {command}: {e}"
247
+ return 1, error_msg
@@ -0,0 +1,110 @@
1
+
2
+ import sys
3
+ import platform
4
+ from unittest import mock
5
+ import io
6
+
7
+ import pytest
8
+
9
+ from autocoder.common.run_cmd import (
10
+ run_cmd,
11
+ run_cmd_subprocess,
12
+ run_cmd_subprocess_generator,
13
+ run_cmd_pexpect,
14
+ get_windows_parent_process_name,
15
+ )
16
+
17
+ def test_run_cmd_basic():
18
+ """
19
+ 测试run_cmd函数,确保其正确执行命令并返回预期结果。
20
+ """
21
+ cmd = "echo hello"
22
+ exit_code, output = run_cmd(cmd)
23
+ assert exit_code == 0, f"命令退出码非零: {exit_code}"
24
+ assert "hello" in output, f"输出不包含hello: {output}"
25
+
26
+ def test_run_cmd_subprocess_normal():
27
+ """
28
+ 测试run_cmd_subprocess正常执行命令,逐步输出。
29
+ """
30
+ cmd = "echo hello_subprocess"
31
+ gen = run_cmd_subprocess_generator(cmd)
32
+ output = ""
33
+ try:
34
+ for chunk in gen:
35
+ output += chunk
36
+ except Exception as e:
37
+ pytest.fail(f"run_cmd_subprocess异常: {e}")
38
+ assert "hello_subprocess" in output
39
+
40
+ def test_run_cmd_subprocess_error():
41
+ """
42
+ 测试run_cmd_subprocess执行错误命令时能否正确返回异常信息。
43
+ """
44
+ cmd = "non_existing_command_xyz"
45
+ gen = run_cmd_subprocess_generator(cmd)
46
+ output = ""
47
+ for chunk in gen:
48
+ output += chunk
49
+ # 应该包含错误提示
50
+ assert "[run_cmd_subprocess error]" in output or "not found" in output or "无法" in output or "未找到" in output
51
+
52
+ def test_run_cmd_pexpect_mock():
53
+ """
54
+ 测试run_cmd_pexpect函数,mock pexpect交互行为。
55
+ """
56
+ with mock.patch("pexpect.spawn") as mock_spawn:
57
+ mock_child = mock.MagicMock()
58
+ mock_child.exitstatus = 0
59
+ mock_child.interact.side_effect = lambda output_filter=None: output_filter(b"mock output\n")
60
+ mock_child.close.return_value = None
61
+ mock_child.exitstatus = 0
62
+ mock_child.getvalue = lambda: b"mock output\n"
63
+ mock_spawn.return_value = mock_child
64
+
65
+ # 由于run_cmd_pexpect内部会decode BytesIO内容
66
+ exit_code, output = run_cmd_pexpect("echo hello", verbose=False)
67
+ assert exit_code == 0
68
+ assert "mock output" in output
69
+
70
+ def test_get_windows_parent_process_name_mocked():
71
+ """
72
+ 测试get_windows_parent_process_name,模拟不同父进程
73
+ """
74
+ if platform.system() != "Windows":
75
+ # 非Windows系统跳过
76
+ return
77
+
78
+ # 构造mock进程树
79
+ class FakeProcess:
80
+ def __init__(self, name, parent=None):
81
+ self._name = name
82
+ self._parent = parent
83
+
84
+ def name(self):
85
+ return self._name
86
+
87
+ def parent(self):
88
+ return self._parent
89
+
90
+ powershell_proc = FakeProcess("powershell.exe")
91
+ cmd_proc = FakeProcess("cmd.exe")
92
+ other_proc = FakeProcess("python.exe")
93
+
94
+ # 模拟powershell父进程
95
+ with mock.patch("psutil.Process") as MockProcess:
96
+ MockProcess.return_value = FakeProcess("python.exe", powershell_proc)
97
+ assert get_windows_parent_process_name() == "powershell.exe"
98
+
99
+ # 模拟cmd父进程
100
+ with mock.patch("psutil.Process") as MockProcess:
101
+ MockProcess.return_value = FakeProcess("python.exe", cmd_proc)
102
+ assert get_windows_parent_process_name() == "cmd.exe"
103
+
104
+ # 模拟无匹配父进程
105
+ with mock.patch("psutil.Process") as MockProcess:
106
+ MockProcess.return_value = FakeProcess("python.exe", other_proc)
107
+ assert get_windows_parent_process_name() is None
108
+
109
+ if __name__ == "__main__":
110
+ sys.exit(pytest.main([__file__]))